ort_workstealing.c

来源:互联网 发布:五子棋游戏c语言代码 编辑:程序博客网 时间:2024/04/29 06:49
#include "ort_prive.h"#include <stdlib.h>#include <stdio.h>#define FAILURE 0#define SUCCESS 1/* Allocate memory for my group task queues */inline void ort_task_queues_init(ort_eecb_t *me, int nthr){  int i;  /* Thread becomes parent for first time */  if (me->tasking.queue_table == NULL)  {//当前线程第一次成为master线程    //创建多个任务队列,每个任务队列对应组内的一个线程    me->tasking.queue_table = (ort_task_queue_t*)                              ort_calloc((nthr + 1)*sizeof(ort_task_queue_t));    for (i=0; i<nthr + 1; i++)    {//对新建的各个任务队列进行初始化      me->tasking.queue_table[i].top         = 0;//初始化队列顶部位置      me->tasking.queue_table[i].bottom      = 0;//初始化队列底部位置      me->tasking.queue_table[i].implicit_task_children = NULL;      me->tasking.queue_table[i].tasks = (ort_task_node_t**)          ort_calloc(TASKQUEUESIZE*sizeof(ort_task_node_t*));//新建多个任务节点的指针空间    }    me->tasking.max_children = nthr + 1;//任务队列的个数  }  else  {//不是第一次成为master线程,不需要重新为这个eecb分配任务队列相关的存储空间    if (me->tasking.max_children < nthr + 1)    {//此时需要重新分配      for (i=0; i<me->tasking.max_children; i++)        free(me->tasking.queue_table[i].tasks);//销毁以前创建的任务节点指针的数组      //增加此队列表的大小      me->tasking.queue_table = (ort_task_queue_t*)         realloc(me->tasking.queue_table, (nthr + 1)*sizeof(ort_task_queue_t));      for (i=0; i<nthr + 1; i++)//新建指针数组来存储多个任务节点指针        me->tasking.queue_table[i].tasks = (ort_task_node_t**) ort_calloc(TASKQUEUESIZE*sizeof(ort_task_node_t*));      me->tasking.max_children = nthr + 1;//设置当前队列表的大小    }    //对任务队列表重新进行初始化    for (i=0; i<nthr + 1; i++)    {      me->tasking.queue_table[i].top      = 0;      me->tasking.queue_table[i].bottom   = 0;      me->tasking.queue_table[i].implicit_task_children = NULL;    }    //不用设置max_children??  }}/* ort_task_worker_enqueue * This function is used by a process (worker) in order to enqueue a new * task_node to its task queue. */inline int ort_task_worker_enqueue(ort_eecb_t *me, void* (*func)(void *), void *arg, int final){//将任务节点入队    ort_task_node_t *new_node;    int worker_id = me->thread_num;//获取当前线程的编号    ort_eecb_t *my_parent = me->sdn;    int old_bottom = atomic_read//读取此线程对应的队列的底部                       (&(my_parent->tasking.queue_table[worker_id].bottom));    new_node = ort_task_alloc(func, arg);//根据参数产生一个新的任务节点    //如果当前任务被继承了,那么新建一个任务节点,并将其设置为但前任务    if(__INHERITASK(me))      ort_create_task_immediate_node(me);    //初始化任务节点参数    new_node->func              = func;    new_node->num_children      = 0;    new_node->next              = NULL;    new_node->parent            = __CURRTASK(me);    new_node->icvs              = new_node->parent->icvs;    new_node->inherit_task_node = 0;    new_node->isfinal           = final;    if(new_node->parent != NULL)    {//给父任务添加了一个子任务      _faa(&((new_node->parent)->num_children),1);    }    //向队列的底部添加一个任务    my_parent->tasking.queue_table[worker_id].tasks[old_bottom%TASKQUEUESIZE] =                                                                       new_node;    my_parent->tasking.queue_table[worker_id].bottom++;//修改队列的底部位置    return SUCCESS;}/* ort_task_worker_dequeue * This function is used by a process (worker) in order to dequeue a * new task_node from its task queue. */inline ort_task_node_t*  ort_task_worker_dequeue(ort_eecb_t *me){    ort_task_node_t* extracting_node;    ort_eecb_t *my_parent = me->sdn;    int worker_id = me->thread_num;//获取当前线程的组内编号    int old_top;    int new_top;    int size;    //获取当前队列的大小    size = atomic_read(&(my_parent->tasking.queue_table[worker_id].bottom))     - atomic_read(&(my_parent->tasking.queue_table[worker_id].top)) -1;    if (size < 0) //表明此时队列是空的      return NULL;    //bottom回到原来的位置    _faa(&(my_parent->tasking.queue_table[worker_id].bottom),-1);    //获取队列的顶部位置    old_top = atomic_read(&(my_parent->tasking.queue_table[worker_id].top));    new_top = old_top + 1;    //获取排除底部的任务节点后队列的大小    size = atomic_read(&(my_parent->tasking.queue_table[worker_id].bottom))               - old_top;    if (size < 0)    {        my_parent->tasking.queue_table[worker_id].bottom = old_top;        return NULL;    }    //返回的任务节点是最后面入队的那个节点    extracting_node = my_parent->tasking.queue_table[worker_id]                          .tasks[atomic_read(&((my_parent->tasking.                               queue_table[worker_id]).bottom))%TASKQUEUESIZE];    if(size > 0)        return extracting_node;    /* If there is only one task left in queue... */      /* If a thief stole the last task... */      if(!_cas(&((my_parent->tasking.queue_table[worker_id]).top),               old_top, new_top))        extracting_node = NULL;/* then return NULL, else return the last task */    /* old_top + 1 = new_top */    my_parent->tasking.queue_table[worker_id].bottom = old_top + 1;    return extracting_node;}inline ort_task_node_t* ort_task_thief_steal(ort_eecb_t *me, int victim_id){    ort_task_node_t *extracting_node;    ort_eecb_t *my_parent = me->sdn;    //获取指定队列的顶部位置    int old_top = atomic_read(&(my_parent->tasking.queue_table[victim_id].top));    int new_top = old_top + 1;    //获取指定队列的底部位置    int old_bottom = atomic_read(&(my_parent->tasking.queue_table[victim_id].bottom));    int size = old_bottom - old_top;    if(size <= 0) /* Victim's queue is empty */        return NULL;    //从队列的顶部获取一个任务节点    extracting_node = my_parent->tasking.queue_table[victim_id]                                        .tasks[old_top%TASKQUEUESIZE];    if(_cas(&((my_parent->tasking.queue_table[victim_id]).top),            old_top, new_top))//修改指定队列的顶部位置      return extracting_node;//返回任务节点    return NULL;}

原创粉丝点击