- Main
- Tutorials
- Library
- Samples

- File List
- Globals

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
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <signal.h>
48 #include <pthread.h>
49 #include <errno.h>
50 #include <sys/time.h>
51 #include <time.h>
52 #include <iothinx/iothinxio.h>
53 #include <sched.h>
54
55 int set_process_priority(int pid, int priority_level)
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 }
88
90 int main(int argc, char **const argv)
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
163 rc = ioThinx_IO_Config_Reload();
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 }
DO_MODE_DO
#define DO_MODE_DO
Definition: iothinxio.h:291
ioThinx_DO_SetValues
IOTHINX_ERR ioThinx_DO_SetValues(uint32_t slot, uint32_t values)
IOTHINX_ERR_OK
#define IOTHINX_ERR_OK
Definition: iothinxio.h:35
ioThinx_DO_Config_SetModes
IOTHINX_ERR ioThinx_DO_Config_SetModes(uint32_t slot, uint8_t start, uint8_t count, uint8_t buf[])
main
int main(int argc, char **const argv)
Definition: scheduling_jitter.c:90
ioThinx_IO_Config_Reload
IOTHINX_ERR ioThinx_IO_Config_Reload(void)
set_process_priority
int set_process_priority(int pid, int priority_level)
Definition: scheduling_jitter.c:55
ioThinx_IO_Client_Init
IOTHINX_ERR ioThinx_IO_Client_Init(void)