Helixis 1.0
Task Programming API
sources/parallel/parallel_sched.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2009-2011, helixis.org
00003 ** All rights reserved.
00004 **
00005 ** Redistribution and use in source and binary forms, with or without modification, are permitted provided
00006 ** that the following conditions are met:
00007 **
00008 ** Redistributions of source code must retain the above copyright notice, this list of conditions and the
00009 ** following disclaimer.
00010 **
00011 ** Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00012 ** the following disclaimer in the documentation and/or other materials provided with the distribution.
00013 **
00014 ** Neither the name of the helixis.org nor the names of its contributors may be used to endorse or promote
00015 ** products derived from this software without specific prior written permission.
00016 **
00017 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00018 ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00019 ** PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00020 ** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00021 ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00022 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00023 ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00024 ** POSSIBILITY OF SUCH DAMAGE.
00025 */
00026 
00027 /*
00028 ** INCLUDES
00029 */
00030 
00031 #include "hlx/core.h"
00032 #include "helixis_internal.h"
00033 
00034 #if defined(HLX_BUILD_WITH_PARALLEL_THREADING)
00035 
00036 #ifdef __cplusplus
00037 extern "C"      {
00038 #endif
00039 
00040 /*
00041 ** EXTERNALS
00042 */
00043 
00044 extern hlx_api gl_api;
00045 
00046 /*
00047 ** GLOBALS
00048 */
00049 
00050 hlx_scheduler   gl_scheduler;
00051 
00052 /*
00053 ** PROTOTYPES
00054 */
00055 
00056 hlx_group* hlx_sheduler_find_lighter_group(void);
00057 hlx_task* hlx_scheduler_init_task(hlx_task_func task_func, void* data, hlx_group* group, hlx_task_callback callback);
00058 void hlx_scheduler_schedule(void);
00059 int  hlx_scheduler_schedule_group(hlx_group*);
00060 void hlx_core_add_task_in_group_callback2(hlx_task_func task_func, void* data, hlx_group_id group_id, hlx_task_callback callback);
00061 
00062 /*
00063 ** FUNCTIONS
00064 */
00065 
00066 void hlx_core_add_task_in_group_callback(hlx_task_func task_func, void* data, hlx_group_id group_id, hlx_group_id self_group_id, hlx_task_callback callback)
00067 {
00068         hlx_task* task;
00069         hlx_group* group;
00070 
00071         group = (hlx_group* )group_id;
00072         if (group_id == self_group_id)
00073         {
00074                 hlx_core_add_task_in_group_callback2(task_func, data, group_id, callback);
00075                 return ;
00076         }
00077         task = hlx_scheduler_init_task(task_func, data, group, callback);
00078         if (!task)
00079                 return;
00080         hlx_group_bufferize_task(group, task);
00081         gl_api.thread_api.thread_resume(&(group->thread));
00082 }
00083 
00084 void hlx_core_add_task_callback(hlx_task_func task_func, void* data, hlx_group_id self_group_id, hlx_task_callback callback)
00085 {
00086         hlx_group* best;
00087 
00088         best = hlx_sheduler_find_lighter_group();
00089         if (best->id == self_group_id)
00090         {
00091                 hlx_core_add_task_in_group_callback2(task_func, data, best->id, callback);
00092                 return;
00093         }
00094         hlx_core_add_task_in_group_callback(task_func, data, best->id, self_group_id, callback);
00095 }
00096 
00097 void hlx_core_add_task_in_group_callback2(hlx_task_func task_func, void* data, hlx_group_id group_id, hlx_task_callback callback)
00098 {
00099         hlx_task* task;
00100         hlx_group* group;
00101 
00102         group = (hlx_group*)group_id;
00103         task = hlx_scheduler_init_task(task_func, data, group, callback);
00104         if (!task)
00105                 return;
00106         if (gl_scheduler.launched)
00107                 hlx_group_bufferize_task(group, task);
00108         else
00109                 hlx_group_add_task(group, task);
00110         gl_api.thread_api.thread_resume(&(group->thread));
00111 }
00112 
00113 void hlx_sheduler_end_all_threads()
00114 {
00115         hlx_list_node* it;
00116         hlx_group* group;
00117 
00118         gl_scheduler.loop = 0;
00119         for (it = gl_scheduler.groups.first; it; it = it->next)
00120         {
00121                 group = it->data;
00122                 gl_api.thread_api.thread_resume(&(group->thread));
00123         }
00124 }
00125 
00126 static void hlx_scheduler_schedule_group_threaded(hlx_thread* thread, void* data)
00127 {
00128         int ret;
00129         hlx_list_node* it;
00130         hlx_list_node* tmp;
00131         hlx_task* task;
00132         hlx_group* group;
00133         hlx_group* tmp_group;
00134 
00135         group = (hlx_group*)data;
00136         tmp_group = (hlx_group*)data;
00137         while (gl_scheduler.loop == 1)
00138         {
00139                 thread->status = HLX_THREAD_LOCKED;
00140                 hlx_group_flush_task_buffer(group);
00141                 if (!group->active_count)
00142                 {
00143                         ret = 0;
00144                         for (it = gl_scheduler.groups.first; it; it = it->next)
00145                         {
00146                                 tmp_group = it->data;
00147                                 if (tmp_group != group && tmp_group->active_count)
00148                                 {
00149                                         ret = 1;
00150                                         break;
00151                                 }
00152                         }
00153                         if (ret)
00154                                 gl_api.thread_api.thread_suspend(thread);
00155                         else if (thread->status == HLX_THREAD_LOCKED)
00156                         {
00157                                 hlx_sheduler_end_all_threads();
00158                                 return;
00159                         }
00160                 }
00161                 gl_api.thread_api.thread_pause_if_needed(thread);
00162                 thread->status = HLX_THREAD_RUNNING;
00163                 it = group->tasks.first;
00164                 while (it)
00165                 {
00166                         task = it->data;
00167                         if (task->status != HLX_TASK_STATUS_RUN)
00168                         {
00169                                 it = it->next;
00170                                 continue;
00171                         }
00172                         ret = task->task_func(&(task->ctx), task->group_id, &(task->stack), task->data);
00173                         if (ret == HLX_ENDED || ret == HLX_EXITED || ret == HLX_MEMORY_EXHAUSTED)
00174                         {
00175                                 if (task->callback != 0)
00176                                         task->callback(task->data, task->group_id, ret);
00177                                 gl_api.atomic_decr_entry(&group->active_count);
00178                                 if (task->stack != 0)
00179                                         gl_api.free_entry(task->stack);
00180                                 gl_api.free_entry(task);
00181                                 tmp = it->next;
00182                                 hlx_list_erase(&group->tasks, it);
00183                                 it = tmp;
00184                         }
00185                         else
00186                                 it = it->next;
00187                 }
00188         }
00189 }
00190 
00191 void hlx_scheduler_schedule(void)
00192 {
00193         hlx_list_node* it;
00194         hlx_group* g;
00195 
00196         gl_scheduler.loop = 1;
00197         gl_scheduler.launched = 1;
00198         for (it = gl_scheduler.groups.first; it != 0; it = it->next)
00199         {
00200                 g = it->data;
00201                 gl_api.thread_api.thread_execute(&g->thread, hlx_scheduler_schedule_group_threaded, g);
00202         }
00203         for (it = gl_scheduler.groups.first; it != 0; it = it->next)
00204         {
00205                 g = it->data;
00206                 gl_api.thread_api.thread_wait_for(&(g->thread));
00207         }
00208         gl_scheduler.launched = 0;
00209 }
00210 
00211 #endif /* !HLX_BUILD_WITH_PARALLEL_THREADING */
00212 
00213 #ifdef __cplusplus
00214 }
00215 #endif
00216 
00217 /*
00218 ** END OF FILE
00219 */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines