scheduling_jitter.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (C) 2019 Moxa Inc. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Scheduling Jitter Sample Application
6  *
7  * Date Author Comment
8  * 2019-04-25 Wanhan Hsieh Created it.
9  ******************************************************************************/
10 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <signal.h>
47 #include <pthread.h>
48 #include <errno.h>
49 #include <sys/time.h>
50 #include <time.h>
51 #include <iothinx/iothinxio.h>
52 #include <sched.h>
53 
54 int set_process_priority(int pid, int priority_level)
55 {
56  int rc = 0;
57  int policy;
58  struct sched_param param = { 0 };
59 
60  switch (priority_level)
61  {
62  case 1: // medium
63  policy = SCHED_RR;
64  param.sched_priority = 1;
65  break;
66  case 2: // high
67  policy = SCHED_RR;
68  param.sched_priority = 49;
69  break;
70  case 3: // max
71  policy = SCHED_RR;
72  param.sched_priority = 99;
73  break;
74  case 0: // low
75  default:
76  policy = SCHED_OTHER;
77  param.sched_priority = 0;
78  break;
79  }
80  rc = sched_setscheduler(pid, policy, &param);
81  if(rc != 0)
82  {
83  perror("sched_setscheduler");
84  }
85  return rc;
86 }
87 
89 int main(int argc, char **const argv)
90 {
91  int32_t rc;
92  uint32_t do_slot = 2;
93  uint8_t do_channel = 0;
94  uint8_t do_mode = DO_MODE_DO;
95  uint32_t do_values = 0;
96  uint32_t test_cnt = 1000;
97  uint32_t cycle_time_us = 10000;
98  uint32_t i;
99  time_t start_time_us, end_time_us;
100  time_t last_start_time_us = 0;
101  int priority_level = 3;
102  int32_t diff_us;
103  int32_t sum_us = 0;
104  int32_t max_us = 0;
105  struct timespec ts;
106 
107  while (-1 != (rc = getopt(argc, argv, "c:hn:p:s:t:")))
108  {
109  switch (rc)
110  {
111  case 'c':
112  do_channel = atoi(optarg);
113  break;
114  case 'n':
115  test_cnt = atoi(optarg);
116  break;
117  case 'p':
118  priority_level = atoi(optarg);
119  break;
120  case 's':
121  do_slot = atoi(optarg);
122  break;
123  case 't':
124  cycle_time_us = atoi(optarg);
125  break;
126  case 'h':
127  default:
128  printf("Scheduling jitter sample program.\n\n");
129  printf("Usage: ./scheduling_jitter [OPTIONS]\n\n");
130  printf("Options: \n");
131  printf("\t %-8s Priority level[0-3]. Default level = %d\n", "-p", priority_level);
132  printf("\t %-8s Slot of DO module. Default slot = %d\n", "-s", do_slot);
133  printf("\t %-8s DO channel. Default channel = %d\n", "-c", do_channel);
134  printf("\t %-8s Testing loop count. Default count = %d\n", "-n", test_cnt);
135  printf("\t %-8s Testing loop cycle time (in us). Default time = %d us\n", "-t", cycle_time_us);
136  printf("\n");
137  return 0;
138  }
139  }
140 
141  printf("Priority level = %d\n", priority_level);
142  printf("DO slot = %lu\n", do_slot);
143  printf("DO channel = %u\n", do_channel);
144 
145  // initialize ioThinx I/O
146  rc = ioThinx_IO_Client_Init();
147  if (rc != IOTHINX_ERR_OK)
148  {
149  printf("ioThinx_IO_Client_Init() = %d\n", rc);
150  return -1;
151  }
152 
153  // temporarily set config
154  rc = ioThinx_DO_Config_SetModes(do_slot, do_channel, 1, &do_mode);
155  if (rc != IOTHINX_ERR_OK)
156  {
157  printf("ioThinx_DO_Config_SetModes() = %d\n", rc);
158  return -1;
159  }
160 
161  // reload config
163  if (rc != IOTHINX_ERR_OK)
164  {
165  printf("ioThinx_IO_Config_Reload() = %d\n", rc);
166  return -1;
167  }
168 
169  // set process priority
170  set_process_priority(0, priority_level);
171  if (rc != 0)
172  {
173  return -1;
174  }
175 
176  printf("Start testing ...\n");
177 
178  for (i = 0; i < test_cnt; i++)
179  {
180  // get start time
181  clock_gettime(CLOCK_MONOTONIC, &ts);
182  start_time_us = (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
183  diff_us = (last_start_time_us == 0) ? 0 : start_time_us - last_start_time_us - cycle_time_us;
184  sum_us += diff_us;
185  max_us = (diff_us > max_us) ? diff_us : max_us;
186  last_start_time_us = start_time_us;
187 
188  // do the stuff ...
189  // invert do value
190  if (do_values & (0x1 << do_channel))
191  {
192  do_values &= ~(0x1 << do_channel);
193  }
194  else
195  {
196  do_values |= 0x1 << do_channel;
197  }
198  rc = ioThinx_DO_SetValues(do_slot, do_values);
199  if (rc != IOTHINX_ERR_OK)
200  {
201  printf("ioThinx_DO_SetValues() = %d\n", rc);
202  break;
203  }
204 
205  // get end time
206  clock_gettime(CLOCK_MONOTONIC, &ts);
207  end_time_us = (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
208 
209  // calculate sleep time
210  diff_us = cycle_time_us - (end_time_us - start_time_us);
211  ts.tv_sec = 0;
212  ts.tv_nsec = diff_us * 1000;
213 
214  // sleep
215  clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
216  }
217 
218  printf("Done.\n");
219  printf("Scheduling jitter: Avg. = %.1f us, Max = %ld us\n",
220  (float)sum_us / (float)(test_cnt - 1), max_us);
221 
222  return 0;
223 }
#define DO_MODE_DO
Definition: iothinxio.h:289
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 main(int argc, char **const argv)
Definition: uart.c:55
IOTHINX_ERR ioThinx_IO_Client_Init(void)