Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
examples to demonstrate bugs in sendrecv
[simgrid.git] / examples / xbt / sem_sched.c
1 #include <stdio.h>\r
2 #include <stdlib.h>\r
3 #include <string.h>\r
4 #include <errno.h>\r
5 \r
6 \r
7 #include "xbt/xbt_os_thread.h"\r
8 #include "xbt.h"\r
9 #include "xbt/log.h"\r
10 XBT_LOG_NEW_DEFAULT_CATEGORY(sem_sched,"Messages specific for this sem example");\r
11 \r
12 #ifndef ENOBUFS\r
13 #define ENOBUFS         1024\r
14 #endif\r
15 \r
16 #define CTX_MAX                 ((unsigned int)1000)\r
17 \r
18 \r
19 #define MAX_ARG                                         30\r
20 #define MAX_ARGS                                        10\r
21 \r
22 typedef int (*pfn_func_t)(int, char**);\r
23 \r
24 static int\r
25 __next_ctx_ID = 0;\r
26 \r
27 typedef struct s_job\r
28 {\r
29         pfn_func_t func;\r
30         int argc;\r
31         char** argv;\r
32 }s_job_t,* job_t;\r
33 \r
34 \r
35 job_t\r
36 job_new(pfn_func_t func, int argc, char** argv);\r
37 \r
38 int\r
39 job_execute(job_t job);\r
40 \r
41 int\r
42 job_free(job_t* ref);\r
43 \r
44 /* an entry of the table of threads */\r
45 typedef struct s_ctx\r
46 {\r
47         xbt_os_sem_t begin;\r
48         xbt_os_sem_t end;\r
49         int failure;\r
50         job_t job;\r
51         xbt_os_thread_t imp;\r
52         int index;\r
53 }s_ctx_t,* ctx_t;\r
54 \r
55 typedef struct s_shed\r
56 {\r
57         ctx_t* ctxs;\r
58         int size;\r
59         int capacity;\r
60 }s_sched_t,* sched_t;\r
61 \r
62 \r
63 void \r
64 schedule(ctx_t c);\r
65 void \r
66 unschedule(ctx_t c);\r
67 \r
68 void*\r
69 ctx_function(void* param);\r
70 \r
71 ctx_t \r
72 ctx_new(job_t job);\r
73 \r
74 int \r
75 ctx_free(ctx_t* ref);\r
76 \r
77 sched_t\r
78 sched_new(int size);\r
79 \r
80 int\r
81 sched_add_job(sched_t sched, job_t job);\r
82 \r
83 int\r
84 sched_init(sched_t sched);\r
85 \r
86 int\r
87 sched_schedule(sched_t sched);\r
88 \r
89 int\r
90 sched_clean(sched_t sched);\r
91 \r
92 int\r
93 sched_free(sched_t* ref);\r
94 \r
95 int\r
96 job(int argc, char* argv[]);\r
97 \r
98 int\r
99 main(int argc, char* argv[])\r
100 {\r
101         sched_t sched;\r
102         int i, size;\r
103         char** __argv;\r
104         char arg[MAX_ARG] = {0};\r
105         \r
106         \r
107         xbt_init(&argc, argv);\r
108         \r
109         if(argc != 2) \r
110         {\r
111                 INFO1("Usage: %s job count",argv[0]);\r
112                 exit(EXIT_FAILURE);\r
113         }  \r
114         \r
115         \r
116         size = atoi(argv[1]);\r
117         \r
118         /* create a new scheduler */\r
119         sched = sched_new(size);\r
120         \r
121         if(!sched)\r
122         {\r
123                 INFO1("sched_new() failed : errno %d",errno);\r
124                 xbt_exit();\r
125                 exit(EXIT_FAILURE);\r
126         }\r
127         \r
128         __argv = xbt_new0(char*,MAX_ARGS);\r
129         \r
130         for(i = 0; i < MAX_ARGS; i++)\r
131         {\r
132                 sprintf(arg,"arg_%d",i);\r
133                 __argv[i] = strdup(arg);\r
134                 memset(arg,0,MAX_ARG);\r
135                 \r
136         }\r
137         \r
138         for(i = 0; i < size; i++)\r
139                 sched_add_job(sched,job_new(job,(i < MAX_ARGS) ? i : MAX_ARGS,__argv));\r
140         \r
141         /* initialize the scheduler */\r
142         if(sched_init(sched) < 0)\r
143         {\r
144                 sched_free(&sched);\r
145                 INFO1("sched_init() failed : errno %d\n",errno);\r
146                 xbt_exit();\r
147                 exit(EXIT_FAILURE);\r
148         }\r
149         \r
150         /* schedule the jobs */\r
151         if(sched_schedule(sched) < 0)\r
152         {\r
153                 sched_free(&sched);\r
154                 INFO1("sched_init() failed : errno %d",errno);\r
155                 xbt_exit();\r
156                 exit(EXIT_FAILURE);\r
157         }\r
158         \r
159         /* cleanup */\r
160         if(sched_clean(sched) < 0)\r
161         {\r
162                 sched_free(&sched);\r
163                 INFO1("sched_init() failed : errno %d",errno);\r
164                 xbt_exit();\r
165                 exit(EXIT_FAILURE);\r
166         }\r
167         \r
168         /* destroy the scheduler */\r
169         sched_free(&sched);\r
170         \r
171         INFO1("sem_sched terminated with exit code %d (success)",EXIT_SUCCESS);\r
172 \r
173         xbt_exit();\r
174         \r
175         return EXIT_SUCCESS;\r
176                 \r
177 }\r
178 \r
179 void*\r
180 ctx_function(void* param)\r
181 {\r
182         int i = 0;\r
183         int exit_code = 1;\r
184         ctx_t ctx = (ctx_t)param;\r
185         \r
186         INFO1("Hello i'm the owner of the context %d, i'm waiting for starting",ctx->index);\r
187         \r
188         unschedule(ctx);\r
189         \r
190         if(ctx->failure)\r
191         {\r
192                 INFO1("0ups the scheduler initialization failed bye {%d}.",ctx->index);\r
193                 xbt_os_thread_exit(&exit_code);\r
194         }\r
195         \r
196         INFO1("I'm the owner of the context %d : I'm started",ctx->index);\r
197         INFO0("Wait a minute, I do my job");\r
198         \r
199         /* do its job */\r
200         exit_code = job_execute(ctx->job);\r
201         \r
202         INFO1("Have finished my job, bye {%d}\n",ctx->index);\r
203         \r
204         xbt_os_sem_release(ctx->end);\r
205         \r
206         xbt_os_thread_exit(&exit_code);\r
207 }\r
208 \r
209 void schedule(ctx_t c) \r
210 {\r
211         xbt_os_sem_release(c->begin);   /* allow C to go                */\r
212         xbt_os_sem_acquire(c->end);     /* wait C's end                 */\r
213 }\r
214 \r
215 void unschedule(ctx_t c) \r
216 {\r
217    xbt_os_sem_release(c->end);          /* I'm done, dude               */\r
218    xbt_os_sem_acquire(c->begin);        /* can I start again?   */\r
219 }\r
220 \r
221 ctx_t \r
222 ctx_new(job_t job)\r
223 {\r
224         ctx_t ctx = xbt_new0(s_ctx_t,1);\r
225         ctx->index = ++__next_ctx_ID;\r
226         ctx->begin = xbt_os_sem_init(0);\r
227         ctx->end = xbt_os_sem_init(0);\r
228         ctx->failure = 0;\r
229         ctx->job = job;\r
230         \r
231         return ctx;\r
232 }\r
233 \r
234 int \r
235 ctx_free(ctx_t* ref)\r
236 {\r
237         ctx_t ctx;\r
238         if(!(*ref))\r
239                 return EINVAL;\r
240         \r
241         ctx = *ref;\r
242         \r
243         xbt_os_sem_destroy(ctx->begin);\r
244         xbt_os_sem_destroy(ctx->end);\r
245         job_free(&(ctx->job));\r
246         free(ctx);\r
247         *ref = NULL;\r
248         \r
249         return 0;\r
250 }\r
251 \r
252 sched_t\r
253 sched_new(int size)\r
254 {\r
255         sched_t sched;\r
256         \r
257         if(size <= 0)\r
258         {\r
259                 errno = EINVAL;\r
260                 return NULL;\r
261         }\r
262         \r
263         sched = xbt_new0(s_sched_t,1);\r
264         \r
265         if(!sched)\r
266         {\r
267                 errno = ENOMEM;\r
268                 return NULL;\r
269         }\r
270                 \r
271         sched->ctxs = xbt_new0(ctx_t,size);\r
272         \r
273         if(!(sched->ctxs))\r
274         {\r
275                 errno = ENOMEM;\r
276                 free(sched);\r
277                 return NULL;\r
278         }\r
279         \r
280         sched->size = 0;\r
281         sched->capacity = size;\r
282         \r
283         return sched;\r
284 }\r
285 \r
286 int\r
287 sched_add_job(sched_t sched, job_t job)\r
288 {\r
289         if(!sched || !job)\r
290                 return EINVAL;\r
291         \r
292         if(sched->capacity < sched->size)\r
293                 return ENOBUFS;\r
294                 \r
295         sched->ctxs[(sched->size)++] = ctx_new(job);\r
296         \r
297         return 0;\r
298 }\r
299 \r
300 int\r
301 sched_init(sched_t sched)\r
302 {\r
303         int i,j;\r
304         int success = 1;\r
305         \r
306         if(!sched)\r
307                 return EINVAL;\r
308         \r
309         for(i = 0; i < sched->size; i++)\r
310         {       \r
311                 sched->ctxs[i]->imp = xbt_os_thread_create("thread",ctx_function,(void*)sched->ctxs[i]);\r
312                 \r
313                 xbt_os_sem_acquire(sched->ctxs[i]->end);\r
314         }\r
315         \r
316         if(!success)\r
317         {\r
318                 for(j = 0; j < i; j++)\r
319                 {\r
320                         sched->ctxs[j]->failure = 1;\r
321                         xbt_os_sem_release(sched->ctxs[j]->begin);\r
322                 }\r
323                         \r
324                 for(j = 0; j < i; j++)\r
325                 {\r
326                         xbt_os_thread_join(sched->ctxs[j]->imp,0);\r
327                         \r
328                         ctx_free(&(sched->ctxs[j]));\r
329                 }\r
330                 \r
331                 return -1;\r
332                                         \r
333         }\r
334         \r
335         return 0;\r
336 }\r
337 \r
338 int\r
339 sched_schedule(sched_t sched)\r
340 {\r
341         int i;\r
342         \r
343         if(!sched)\r
344                 return EINVAL;\r
345                 \r
346         for(i = 0; i < sched->size; i++)\r
347                 schedule(sched->ctxs[i]);\r
348                 \r
349         return 0;\r
350 }\r
351 \r
352 int\r
353 sched_clean(sched_t sched)\r
354 {\r
355         int i;\r
356         \r
357         if(!sched)\r
358                 return EINVAL;\r
359                 \r
360         for(i = 0; i < sched->size; i++)\r
361         {\r
362                 xbt_os_thread_join(sched->ctxs[i]->imp,NULL);\r
363                 \r
364                 ctx_free(&(sched->ctxs[i]));\r
365         }\r
366         \r
367         return 0;\r
368 }\r
369 \r
370 int\r
371 sched_free(sched_t* ref)\r
372 {\r
373         if(*ref)\r
374                 return EINVAL;\r
375                 \r
376         free(((sched_t)(*ref))->ctxs);\r
377         \r
378         *ref = NULL;\r
379         \r
380         return 0;\r
381 }\r
382 \r
383 \r
384 int\r
385 job(int argc, char** argv)\r
386 {\r
387         int i = 0;\r
388         \r
389         INFO0("I'm the job : I'm going to print all the args of my commande line");\r
390         \r
391         INFO1("-- Arguments (%d):",argc);\r
392         \r
393         for(i = 0; i < argc; i++)\r
394                 INFO2("  ---- [%i] %s",i,argv[i]);\r
395                 \r
396         return 0;\r
397 }\r
398 \r
399 job_t\r
400 job_new(pfn_func_t func, int argc, char** argv)\r
401 {\r
402         job_t job;\r
403         int i;\r
404         \r
405         /* todo check the parameters */\r
406         job = xbt_new0(s_job_t,1);\r
407         \r
408         if(!job)\r
409         {\r
410                 errno = ENOMEM;\r
411                 return NULL;\r
412         }\r
413         \r
414         job->argv = xbt_new0(char*,argc);\r
415         \r
416         if(!(job->argv))\r
417         {\r
418                 free(job);\r
419                 errno = ENOMEM;\r
420                 return NULL;\r
421         }\r
422         \r
423         for(i = 0; i < argc; i++)\r
424                 job->argv[i] = strdup(argv[i]);\r
425         \r
426         job->func = func;       \r
427         job->argc = argc;\r
428         \r
429         return job;\r
430 }\r
431 \r
432 int\r
433 job_execute(job_t job)\r
434 {\r
435         if(!job)\r
436                 return EINVAL;\r
437                 \r
438         return (*(job->func))(job->argc, job->argv);\r
439 }\r
440 \r
441 int\r
442 job_free(job_t* ref)\r
443 {\r
444         job_t job;\r
445         int i;\r
446         \r
447         if(!(*ref))\r
448                 return EINVAL;\r
449                 \r
450         job = *ref;\r
451         \r
452         for(i = 0; i < job->argc; i++)\r
453                 free(job->argv[i]);\r
454         \r
455         free(job->argv);\r
456         free(*ref);\r
457         *ref = NULL;\r
458         \r
459         return 0;\r
460 }\r
461 \r
462 \r
463 \r