--- /dev/null
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+\r
+#include "xbt/xbt_os_thread.h"\r
+#include "xbt.h"\r
+#include "xbt/log.h"\r
+XBT_LOG_NEW_DEFAULT_CATEGORY(sem_basic,"Messages specific for this sem example");\r
+\r
+\r
+\r
+#define THREAD_THREADS_MAX ((unsigned int)10)\r
+\r
+/*\r
+ * the thread funtion.\r
+ */\r
+void*\r
+thread_routine(void* param);\r
+\r
+/* an entry of the table of threads */\r
+typedef struct s_thread_entry\r
+{\r
+ xbt_os_thread_t thread;\r
+ unsigned int thread_index; /* the index of the thread */\r
+}s_thread_entry_t,* thread_entry_t;\r
+\r
+\r
+static xbt_os_sem_t \r
+sem = NULL;\r
+\r
+static\r
+int value = 0;\r
+int\r
+main(int argc, char* argv[])\r
+{\r
+ s_thread_entry_t threads_table[THREAD_THREADS_MAX] = {0}; \r
+ unsigned int i,j;\r
+ int exit_code = 0;\r
+ \r
+ xbt_init(&argc,argv);\r
+ \r
+ sem = xbt_os_sem_init(1);\r
+ \r
+ i = 0;\r
+ \r
+ while(i < THREAD_THREADS_MAX)\r
+ {\r
+ threads_table[i].thread_index = i;\r
+\r
+ if(NULL == (threads_table[i].thread = xbt_os_thread_create("thread",thread_routine,&(threads_table[i].thread_index))))\r
+ break;\r
+ \r
+ i++;\r
+ }\r
+ \r
+ /* close the thread handles */\r
+ for(j = 0; j < THREAD_THREADS_MAX; j++)\r
+ xbt_os_thread_join(threads_table[j].thread,NULL);\r
+ \r
+ xbt_os_sem_destroy(sem);\r
+ \r
+ INFO1("sem_basic terminated with exit code %d (success)",EXIT_SUCCESS);\r
+\r
+ xbt_exit();\r
+ \r
+ return EXIT_SUCCESS;\r
+ \r
+}\r
+\r
+void*\r
+thread_routine(void* param)\r
+{\r
+ int thread_index = *((int*)param);\r
+ int exit_code = 0;\r
+ \r
+ xbt_os_sem_acquire(sem);\r
+ INFO1("Hello i'm the thread %d",thread_index);\r
+ value++;\r
+ INFO1("The new value of the global variable is %d, bye",value);\r
+ xbt_os_sem_release(sem);\r
+ \r
+ xbt_os_thread_exit(&exit_code);\r
+\r
+ return (void*)(NULL);\r
+}\r
+\r
+\r
+\r
--- /dev/null
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <errno.h>\r
+\r
+\r
+#include "xbt/xbt_os_thread.h"\r
+#include "xbt.h"\r
+#include "xbt/log.h"\r
+XBT_LOG_NEW_DEFAULT_CATEGORY(sem_sched,"Messages specific for this sem example");\r
+\r
+#ifndef ENOBUFS\r
+#define ENOBUFS 1024\r
+#endif\r
+\r
+#define CTX_MAX ((unsigned int)1000)\r
+\r
+\r
+#define MAX_ARG 30\r
+#define MAX_ARGS 10\r
+\r
+typedef int (*pfn_func_t)(int, char**);\r
+\r
+static int\r
+__next_ctx_ID = 0;\r
+\r
+typedef struct s_job\r
+{\r
+ pfn_func_t func;\r
+ int argc;\r
+ char** argv;\r
+}s_job_t,* job_t;\r
+\r
+\r
+job_t\r
+job_new(pfn_func_t func, int argc, char** argv);\r
+\r
+int\r
+job_execute(job_t job);\r
+\r
+int\r
+job_free(job_t* ref);\r
+\r
+/* an entry of the table of threads */\r
+typedef struct s_ctx\r
+{\r
+ xbt_os_sem_t begin;\r
+ xbt_os_sem_t end;\r
+ int failure;\r
+ job_t job;\r
+ xbt_os_thread_t imp;\r
+ int index;\r
+}s_ctx_t,* ctx_t;\r
+\r
+typedef struct s_shed\r
+{\r
+ ctx_t* ctxs;\r
+ int size;\r
+ int capacity;\r
+}s_sched_t,* sched_t;\r
+\r
+\r
+void \r
+schedule(ctx_t c);\r
+void \r
+unschedule(ctx_t c);\r
+\r
+void*\r
+ctx_function(void* param);\r
+\r
+ctx_t \r
+ctx_new(job_t job);\r
+\r
+int \r
+ctx_free(ctx_t* ref);\r
+\r
+sched_t\r
+sched_new(int size);\r
+\r
+int\r
+sched_add_job(sched_t sched, job_t job);\r
+\r
+int\r
+sched_init(sched_t sched);\r
+\r
+int\r
+sched_schedule(sched_t sched);\r
+\r
+int\r
+sched_clean(sched_t sched);\r
+\r
+int\r
+sched_free(sched_t* ref);\r
+\r
+int\r
+job(int argc, char* argv[]);\r
+\r
+int\r
+main(int argc, char* argv[])\r
+{\r
+ sched_t sched;\r
+ int i, size;\r
+ char** __argv;\r
+ char arg[MAX_ARG] = {0};\r
+ \r
+ \r
+ xbt_init(&argc, argv);\r
+ \r
+ if(argc != 2) \r
+ {\r
+ INFO1("Usage: %s job count",argv[0]);\r
+ exit(EXIT_FAILURE);\r
+ } \r
+ \r
+ \r
+ size = atoi(argv[1]);\r
+ \r
+ /* create a new scheduler */\r
+ sched = sched_new(size);\r
+ \r
+ if(!sched)\r
+ {\r
+ INFO1("sched_new() failed : errno %d",errno);\r
+ xbt_exit();\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ \r
+ __argv = (char**)calloc(MAX_ARGS,sizeof(char*));\r
+ \r
+ for(i = 0; i < MAX_ARGS; i++)\r
+ {\r
+ sprintf(arg,"arg_%d",i);\r
+ __argv[i] = strdup(arg);\r
+ memset(arg,0,MAX_ARG);\r
+ \r
+ }\r
+ \r
+ for(i = 0; i < size; i++)\r
+ sched_add_job(sched,job_new(job,(i < MAX_ARGS) ? i : MAX_ARGS,__argv));\r
+ \r
+ /* initialize the scheduler */\r
+ if(sched_init(sched) < 0)\r
+ {\r
+ sched_free(&sched);\r
+ INFO1("sched_init() failed : errno %d\n",errno);\r
+ xbt_exit();\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ \r
+ /* schedule the jobs */\r
+ if(sched_schedule(sched) < 0)\r
+ {\r
+ sched_free(&sched);\r
+ INFO1("sched_init() failed : errno %d",errno);\r
+ xbt_exit();\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ \r
+ /* cleanup */\r
+ if(sched_clean(sched) < 0)\r
+ {\r
+ sched_free(&sched);\r
+ INFO1("sched_init() failed : errno %d",errno);\r
+ xbt_exit();\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ \r
+ /* destroy the scheduler */\r
+ sched_free(&sched);\r
+ \r
+ INFO1("sem_sched terminated with exit code %d (success)",EXIT_SUCCESS);\r
+\r
+ xbt_exit();\r
+ \r
+ return EXIT_SUCCESS;\r
+ \r
+}\r
+\r
+void*\r
+ctx_function(void* param)\r
+{\r
+ int i = 0;\r
+ int exit_code = 1;\r
+ ctx_t ctx = (ctx_t)param;\r
+ \r
+ INFO1("Hello i'm the owner of the context %d, i'm waiting for starting",ctx->index);\r
+ \r
+ unschedule(ctx);\r
+ \r
+ if(ctx->failure)\r
+ {\r
+ INFO1("0ups the scheduler initialization failed bye {%d}.",ctx->index);\r
+ xbt_os_thread_exit(&exit_code);\r
+ }\r
+ \r
+ INFO1("I'm the owner of the context %d : I'm started",ctx->index);\r
+ INFO0("Wait a minute, I do my job");\r
+ \r
+ /* do its job */\r
+ exit_code = job_execute(ctx->job);\r
+ \r
+ INFO1("Have finished my job, bye {%d}\n",ctx->index);\r
+ \r
+ xbt_os_sem_release(ctx->end);\r
+ \r
+ xbt_os_thread_exit(&exit_code);\r
+}\r
+\r
+void schedule(ctx_t c) \r
+{\r
+ xbt_os_sem_release(c->begin); /* allow C to go */\r
+ xbt_os_sem_acquire(c->end); /* wait C's end */\r
+}\r
+\r
+void unschedule(ctx_t c) \r
+{\r
+ xbt_os_sem_release(c->end); /* I'm done, dude */\r
+ xbt_os_sem_acquire(c->begin); /* can I start again? */\r
+}\r
+\r
+ctx_t \r
+ctx_new(job_t job)\r
+{\r
+ ctx_t ctx = (ctx_t)calloc(1,sizeof(s_ctx_t));\r
+ ctx->index = ++__next_ctx_ID;\r
+ ctx->begin = xbt_os_sem_init(0);\r
+ ctx->end = xbt_os_sem_init(0);\r
+ ctx->failure = 0;\r
+ ctx->job = job;\r
+ \r
+ return ctx;\r
+}\r
+\r
+int \r
+ctx_free(ctx_t* ref)\r
+{\r
+ ctx_t ctx;\r
+ if(!(*ref))\r
+ return EINVAL;\r
+ \r
+ ctx = *ref;\r
+ \r
+ xbt_os_sem_destroy(ctx->begin);\r
+ xbt_os_sem_destroy(ctx->end);\r
+ job_free(&(ctx->job));\r
+ free(ctx);\r
+ *ref = NULL;\r
+ \r
+ return 0;\r
+}\r
+\r
+sched_t\r
+sched_new(int size)\r
+{\r
+ sched_t sched;\r
+ \r
+ if(size <= 0)\r
+ {\r
+ errno = EINVAL;\r
+ return NULL;\r
+ }\r
+ \r
+ sched = (sched_t)calloc(1,sizeof(s_sched_t));\r
+ \r
+ if(!sched)\r
+ {\r
+ errno = ENOMEM;\r
+ return NULL;\r
+ }\r
+ \r
+ sched->ctxs = (ctx_t*)calloc(size,sizeof(ctx_t));\r
+ \r
+ if(!(sched->ctxs))\r
+ {\r
+ errno = ENOMEM;\r
+ free(sched);\r
+ return NULL;\r
+ }\r
+ \r
+ sched->size = 0;\r
+ sched->capacity = size;\r
+ \r
+ return sched;\r
+}\r
+\r
+int\r
+sched_add_job(sched_t sched, job_t job)\r
+{\r
+ if(!sched || !job)\r
+ return EINVAL;\r
+ \r
+ if(sched->capacity < sched->size)\r
+ return ENOBUFS;\r
+ \r
+ sched->ctxs[(sched->size)++] = ctx_new(job);\r
+ \r
+ return 0;\r
+}\r
+\r
+int\r
+sched_init(sched_t sched)\r
+{\r
+ int i,j;\r
+ int success = 1;\r
+ \r
+ if(!sched)\r
+ return EINVAL;\r
+ \r
+ for(i = 0; i < sched->size; i++)\r
+ { \r
+ sched->ctxs[i]->imp = xbt_os_thread_create("thread",ctx_function,(void*)sched->ctxs[i]);\r
+ \r
+ xbt_os_sem_acquire(sched->ctxs[i]->end);\r
+ }\r
+ \r
+ if(!success)\r
+ {\r
+ for(j = 0; j < i; j++)\r
+ {\r
+ sched->ctxs[j]->failure = 1;\r
+ xbt_os_sem_release(sched->ctxs[j]->begin);\r
+ }\r
+ \r
+ for(j = 0; j < i; j++)\r
+ {\r
+ xbt_os_thread_join(sched->ctxs[j]->imp,0);\r
+ \r
+ ctx_free(&(sched->ctxs[j]));\r
+ }\r
+ \r
+ return -1;\r
+ \r
+ }\r
+ \r
+ return 0;\r
+}\r
+\r
+int\r
+sched_schedule(sched_t sched)\r
+{\r
+ int i;\r
+ \r
+ if(!sched)\r
+ return EINVAL;\r
+ \r
+ for(i = 0; i < sched->size; i++)\r
+ schedule(sched->ctxs[i]);\r
+ \r
+ return 0;\r
+}\r
+\r
+int\r
+sched_clean(sched_t sched)\r
+{\r
+ int i;\r
+ \r
+ if(!sched)\r
+ return EINVAL;\r
+ \r
+ for(i = 0; i < sched->size; i++)\r
+ {\r
+ xbt_os_thread_join(sched->ctxs[i]->imp,NULL);\r
+ \r
+ ctx_free(&(sched->ctxs[i]));\r
+ }\r
+ \r
+ return 0;\r
+}\r
+\r
+int\r
+sched_free(sched_t* ref)\r
+{\r
+ if(*ref)\r
+ return EINVAL;\r
+ \r
+ free(((sched_t)(*ref))->ctxs);\r
+ \r
+ *ref = NULL;\r
+ \r
+ return 0;\r
+}\r
+\r
+\r
+int\r
+job(int argc, char** argv)\r
+{\r
+ int i = 0;\r
+ \r
+ INFO0("I'm the job : I'm going to print all the args of my commande line");\r
+ \r
+ INFO1("-- Arguments (%d):",argc);\r
+ \r
+ for(i = 0; i < argc; i++)\r
+ INFO2(" ---- [%i] %s",i,argv[i]);\r
+ \r
+ return 0;\r
+}\r
+\r
+job_t\r
+job_new(pfn_func_t func, int argc, char** argv)\r
+{\r
+ job_t job;\r
+ int i;\r
+ \r
+ /* todo check the parameters */\r
+ job = (job_t)calloc(1,sizeof(s_job_t));\r
+ \r
+ if(!job)\r
+ {\r
+ errno = ENOMEM;\r
+ return NULL;\r
+ }\r
+ \r
+ job->argv = (char**)calloc(argc,sizeof(char*));\r
+ \r
+ if(!(job->argv))\r
+ {\r
+ free(job);\r
+ errno = ENOMEM;\r
+ return NULL;\r
+ }\r
+ \r
+ for(i = 0; i < argc; i++)\r
+ job->argv[i] = strdup(argv[i]);\r
+ \r
+ job->func = func; \r
+ job->argc = argc;\r
+ \r
+ return job;\r
+}\r
+\r
+int\r
+job_execute(job_t job)\r
+{\r
+ if(!job)\r
+ return EINVAL;\r
+ \r
+ return (*(job->func))(job->argc, job->argv);\r
+}\r
+\r
+int\r
+job_free(job_t* ref)\r
+{\r
+ job_t job;\r
+ int i;\r
+ \r
+ if(!(*ref))\r
+ return EINVAL;\r
+ \r
+ job = *ref;\r
+ \r
+ for(i = 0; i < job->argc; i++)\r
+ free(job->argv[i]);\r
+ \r
+ free(job->argv);\r
+ free(*ref);\r
+ *ref = NULL;\r
+ \r
+ return 0;\r
+}\r
+\r
+\r
+\r