Functions
scheduling_jitter.c File Reference

Scheduling Jitter Sample More...

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <sys/time.h>
#include <time.h>
#include <iothinx/iothinxio.h>
#include <sched.h>

Go to the source code of this file.

Functions

int set_process_priority (int pid, int priority_level)
 
int main (int argc, char **const argv)
 

Detailed Description

Scheduling Jitter Sample

Date
2019-04-25
Author
Wanhan Hsieh
Version
V1.0
Introduction:
This is Scheduling jitter sample code.
Example:
1. Using default: ./scheduling_jitter
2. Setting test count and cycle time: ./scheduling_jitter -n100 -t100000
3. Setting process priority: ./scheduling_jitter -p3
4. Setting DO slot and channel: ./scheduling_jitter -s3 -c2
Help:
moxa@Moxa:~$ sudo ./scheduling_jitter -h
Scheduling jitter sample program.

Usage: ./scheduling_jitter [OPTIONS]

Options:
     -p       Priority level[0-3]. Default level = 3
     -s       Slot of DO module. Default slot = 2
     -c       DO channel. Default channel = 0
     -n       Testing loop count. Default count = 1000
     -t       Testing loop cycle time (in us). Default time = 10000 us

Definition in file scheduling_jitter.c.

Function Documentation

int set_process_priority ( int  pid,
int  priority_level 
)

Definition at line 55 of file scheduling_jitter.c.

56 {
57  int rc = 0;
58  int policy;
59  struct sched_param param = { 0 };
60 
61  switch (priority_level)
62  {
63  case 1: // medium
64  policy = SCHED_RR;
65  param.sched_priority = 1;
66  break;
67  case 2: // high
68  policy = SCHED_RR;
69  param.sched_priority = 49;
70  break;
71  case 3: // max
72  policy = SCHED_RR;
73  param.sched_priority = 99;
74  break;
75  case 0: // low
76  default:
77  policy = SCHED_OTHER;
78  param.sched_priority = 0;
79  break;
80  }
81  rc = sched_setscheduler(pid, policy, &param);
82  if (rc != 0)
83  {
84  perror("sched_setscheduler");
85  }
86  return rc;
87 }
int main ( int  argc,
char **const  argv 
)
/*******************************************************************************
* Copyright (C) 2019 Moxa Inc. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Scheduling Jitter Sample Application
*
* Date Author Comment
* 2019-04-25 Wanhan Hsieh Created it.
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <sys/time.h>
#include <time.h>
#include <iothinx/iothinxio.h>
#include <sched.h>
int set_process_priority(int pid, int priority_level)
{
int rc = 0;
int policy;
struct sched_param param = { 0 };
switch (priority_level)
{
case 1: // medium
policy = SCHED_RR;
param.sched_priority = 1;
break;
case 2: // high
policy = SCHED_RR;
param.sched_priority = 49;
break;
case 3: // max
policy = SCHED_RR;
param.sched_priority = 99;
break;
case 0: // low
default:
policy = SCHED_OTHER;
param.sched_priority = 0;
break;
}
rc = sched_setscheduler(pid, policy, &param);
if (rc != 0)
{
perror("sched_setscheduler");
}
return rc;
}
int main(int argc, char **const argv)
{
int32_t rc;
uint32_t do_slot = 2;
uint8_t do_channel = 0;
uint8_t do_mode = DO_MODE_DO;
uint32_t do_values = 0;
uint32_t test_cnt = 1000;
uint32_t cycle_time_us = 10000;
uint32_t i;
time_t start_time_us, end_time_us;
time_t last_start_time_us = 0;
int priority_level = 3;
int32_t diff_us;
int32_t sum_us = 0;
int32_t max_us = 0;
struct timespec ts;
while (-1 != (rc = getopt(argc, argv, "c:hn:p:s:t:")))
{
switch (rc)
{
case 'c':
do_channel = atoi(optarg);
break;
case 'n':
test_cnt = atoi(optarg);
break;
case 'p':
priority_level = atoi(optarg);
break;
case 's':
do_slot = atoi(optarg);
break;
case 't':
cycle_time_us = atoi(optarg);
break;
case 'h':
default:
printf("Scheduling jitter sample program.\n\n");
printf("Usage: ./scheduling_jitter [OPTIONS]\n\n");
printf("Options: \n");
printf("\t %-8s Priority level[0-3]. Default level = %d\n", "-p", priority_level);
printf("\t %-8s Slot of DO module. Default slot = %d\n", "-s", do_slot);
printf("\t %-8s DO channel. Default channel = %d\n", "-c", do_channel);
printf("\t %-8s Testing loop count. Default count = %d\n", "-n", test_cnt);
printf("\t %-8s Testing loop cycle time (in us). Default time = %d us\n", "-t", cycle_time_us);
printf("\n");
return 0;
}
}
printf("Priority level = %d\n", priority_level);
printf("DO slot = %lu\n", do_slot);
printf("DO channel = %u\n", do_channel);
// initialize ioThinx I/O
if (rc != IOTHINX_ERR_OK)
{
printf("ioThinx_IO_Client_Init() = %d\n", rc);
return -1;
}
// temporarily set config
rc = ioThinx_DO_Config_SetModes(do_slot, do_channel, 1, &do_mode);
if (rc != IOTHINX_ERR_OK)
{
printf("ioThinx_DO_Config_SetModes() = %d\n", rc);
return -1;
}
// reload config
if (rc != IOTHINX_ERR_OK)
{
printf("ioThinx_IO_Config_Reload() = %d\n", rc);
return -1;
}
// set process priority
set_process_priority(0, priority_level);
if (rc != 0)
{
return -1;
}
printf("Start testing ...\n");
for (i = 0; i < test_cnt; i++)
{
// get start time
clock_gettime(CLOCK_MONOTONIC, &ts);
start_time_us = (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
diff_us = (last_start_time_us == 0) ? 0 : start_time_us - last_start_time_us - cycle_time_us;
sum_us += diff_us;
max_us = (diff_us > max_us) ? diff_us : max_us;
last_start_time_us = start_time_us;
// do the stuff ...
// invert do value
if (do_values & (0x1 << do_channel))
{
do_values &= ~(0x1 << do_channel);
}
else
{
do_values |= 0x1 << do_channel;
}
rc = ioThinx_DO_SetValues(do_slot, do_values);
if (rc != IOTHINX_ERR_OK)
{
printf("ioThinx_DO_SetValues() = %d\n", rc);
break;
}
// get end time
clock_gettime(CLOCK_MONOTONIC, &ts);
end_time_us = (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
// calculate sleep time
diff_us = cycle_time_us - (end_time_us - start_time_us);
ts.tv_sec = 0;
ts.tv_nsec = diff_us * 1000;
// sleep
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
}
printf("Done.\n");
printf("Scheduling jitter: Avg. = %.1f us, Max = %ld us\n",
(float)sum_us / (float)(test_cnt - 1), max_us);
return 0;
}

Definition at line 90 of file scheduling_jitter.c.

91 {
92  int32_t rc;
93  uint32_t do_slot = 2;
94  uint8_t do_channel = 0;
95  uint8_t do_mode = DO_MODE_DO;
96  uint32_t do_values = 0;
97  uint32_t test_cnt = 1000;
98  uint32_t cycle_time_us = 10000;
99  uint32_t i;
100  time_t start_time_us, end_time_us;
101  time_t last_start_time_us = 0;
102  int priority_level = 3;
103  int32_t diff_us;
104  int32_t sum_us = 0;
105  int32_t max_us = 0;
106  struct timespec ts;
107 
108  while (-1 != (rc = getopt(argc, argv, "c:hn:p:s:t:")))
109  {
110  switch (rc)
111  {
112  case 'c':
113  do_channel = atoi(optarg);
114  break;
115  case 'n':
116  test_cnt = atoi(optarg);
117  break;
118  case 'p':
119  priority_level = atoi(optarg);
120  break;
121  case 's':
122  do_slot = atoi(optarg);
123  break;
124  case 't':
125  cycle_time_us = atoi(optarg);
126  break;
127  case 'h':
128  default:
129  printf("Scheduling jitter sample program.\n\n");
130  printf("Usage: ./scheduling_jitter [OPTIONS]\n\n");
131  printf("Options: \n");
132  printf("\t %-8s Priority level[0-3]. Default level = %d\n", "-p", priority_level);
133  printf("\t %-8s Slot of DO module. Default slot = %d\n", "-s", do_slot);
134  printf("\t %-8s DO channel. Default channel = %d\n", "-c", do_channel);
135  printf("\t %-8s Testing loop count. Default count = %d\n", "-n", test_cnt);
136  printf("\t %-8s Testing loop cycle time (in us). Default time = %d us\n", "-t", cycle_time_us);
137  printf("\n");
138  return 0;
139  }
140  }
141 
142  printf("Priority level = %d\n", priority_level);
143  printf("DO slot = %lu\n", do_slot);
144  printf("DO channel = %u\n", do_channel);
145 
146  // initialize ioThinx I/O
147  rc = ioThinx_IO_Client_Init();
148  if (rc != IOTHINX_ERR_OK)
149  {
150  printf("ioThinx_IO_Client_Init() = %d\n", rc);
151  return -1;
152  }
153 
154  // temporarily set config
155  rc = ioThinx_DO_Config_SetModes(do_slot, do_channel, 1, &do_mode);
156  if (rc != IOTHINX_ERR_OK)
157  {
158  printf("ioThinx_DO_Config_SetModes() = %d\n", rc);
159  return -1;
160  }
161 
162  // reload config
164  if (rc != IOTHINX_ERR_OK)
165  {
166  printf("ioThinx_IO_Config_Reload() = %d\n", rc);
167  return -1;
168  }
169 
170  // set process priority
171  set_process_priority(0, priority_level);
172  if (rc != 0)
173  {
174  return -1;
175  }
176 
177  printf("Start testing ...\n");
178 
179  for (i = 0; i < test_cnt; i++)
180  {
181  // get start time
182  clock_gettime(CLOCK_MONOTONIC, &ts);
183  start_time_us = (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
184  diff_us = (last_start_time_us == 0) ? 0 : start_time_us - last_start_time_us - cycle_time_us;
185  sum_us += diff_us;
186  max_us = (diff_us > max_us) ? diff_us : max_us;
187  last_start_time_us = start_time_us;
188 
189  // do the stuff ...
190  // invert do value
191  if (do_values & (0x1 << do_channel))
192  {
193  do_values &= ~(0x1 << do_channel);
194  }
195  else
196  {
197  do_values |= 0x1 << do_channel;
198  }
199  rc = ioThinx_DO_SetValues(do_slot, do_values);
200  if (rc != IOTHINX_ERR_OK)
201  {
202  printf("ioThinx_DO_SetValues() = %d\n", rc);
203  break;
204  }
205 
206  // get end time
207  clock_gettime(CLOCK_MONOTONIC, &ts);
208  end_time_us = (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
209 
210  // calculate sleep time
211  diff_us = cycle_time_us - (end_time_us - start_time_us);
212  ts.tv_sec = 0;
213  ts.tv_nsec = diff_us * 1000;
214 
215  // sleep
216  clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
217  }
218 
219  printf("Done.\n");
220  printf("Scheduling jitter: Avg. = %.1f us, Max = %ld us\n",
221  (float)sum_us / (float)(test_cnt - 1), max_us);
222 
223  return 0;
224 }
#define DO_MODE_DO
Definition: iothinxio.h:291
IOTHINX_ERR ioThinx_DO_SetValues(uint32_t slot, uint32_t values)
#define IOTHINX_ERR_OK
Definition: iothinxio.h:35
IOTHINX_ERR ioThinx_DO_Config_SetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
IOTHINX_ERR ioThinx_IO_Config_Reload(void)
int set_process_priority(int pid, int priority_level)
IOTHINX_ERR ioThinx_IO_Client_Init(void)