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;}