/* * ======== node_change_priority ======== * Purpose: * Change the priority of a node in the allocated state, or that is * currently running or paused on the target. */ int node_change_priority(struct node_object *hnode, s32 prio) { struct node_object *pnode = (struct node_object *)hnode; struct node_mgr *hnode_mgr = NULL; enum node_type node_type; enum node_state state; int status = 0; u32 proc_id; DBC_REQUIRE(refs > 0); if (!hnode || !hnode->hnode_mgr) { status = -EFAULT; } else { hnode_mgr = hnode->hnode_mgr; node_type = node_get_type(hnode); if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET) status = -EPERM; else if (prio < hnode_mgr->min_pri || prio > hnode_mgr->max_pri) status = -EDOM; } if (status) goto func_end; /* Enter critical section */ mutex_lock(&hnode_mgr->node_mgr_lock); state = node_get_state(hnode); if (state == NODE_ALLOCATED || state == NODE_PAUSED) { NODE_SET_PRIORITY(hnode, prio); } else { if (state != NODE_RUNNING) { status = -EBADR; goto func_cont; } status = proc_get_processor_id(pnode->hprocessor, &proc_id); if (proc_id == DSP_UNIT) { status = disp_node_change_priority(hnode_mgr->disp_obj, hnode, hnode_mgr->ul_fxn_addrs [RMSCHANGENODEPRIORITY], hnode->node_env, prio); } if (status >= 0) NODE_SET_PRIORITY(hnode, prio); } func_cont: /* Leave critical section */ mutex_unlock(&hnode_mgr->node_mgr_lock); func_end: return status; }
/* * Handle a given task */ static void handle_task(node_t node, msg_task_t task) { XBT_DEBUG("Handling task %p", task); char mailbox[MAILBOX_NAME_SIZE]; int i, j, min, max, d; msg_task_t task_sent; task_data_t req_data; task_data_t task_data = (task_data_t) MSG_task_get_data(task); e_task_type_t type = task_data->type; // If the node is not ready keep the task for later if (node->ready != 0 && !(type==TASK_JOIN_LAST_REPLY || type==TASK_JOIN_REPLY)) { XBT_DEBUG("Task pending %i", type); xbt_fifo_push(node->pending_tasks, task); return; } switch (type) { /* * Try to join the ring */ case TASK_JOIN: { int next = routing_next(node, task_data->answer_id); XBT_DEBUG("Join request from %08x forwarding to %08x", task_data->answer_id, next); type = TASK_JOIN_LAST_REPLY; req_data = xbt_new0(s_task_data_t,1); req_data->answer_id = task_data->sender_id; req_data->steps = task_data->steps + 1; // if next different from current node forward the join if (next!=node->id) { get_mailbox(next, mailbox); task_data->sender_id = node->id; task_data->steps++; task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, task_data); MSG_task_send_with_timeout(task_sent, mailbox, timeout); type = TASK_JOIN_REPLY; } // send back the current node state to the joining node req_data->type = type; req_data->sender_id = node->id; get_mailbox(node->id, req_data->answer_to); req_data->state = node_get_state(node); task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data); MSG_task_send_with_timeout(task_sent, task_data->answer_to, timeout); break; } /* * Join reply from all the node touched by the join */ case TASK_JOIN_LAST_REPLY: // if last node touched reply, copy its namespace set // TODO: it's work only if the two nodes are side to side (is it really the case ?) j = (task_data->sender_id < node->id) ? -1 : 0; for (i=0; i<NAMESPACE_SIZE/2; i++) { node->namespace_set[i] = task_data->state->namespace_set[i-j]; node->namespace_set[NAMESPACE_SIZE-1-i] = task_data->state->namespace_set[NAMESPACE_SIZE-1-i-j-1]; } node->namespace_set[NAMESPACE_SIZE/2+j] = task_data->sender_id; node->ready += task_data->steps + 1; case TASK_JOIN_REPLY: XBT_DEBUG("Joining Reply"); // if first node touched reply, copy its neighborood set if (task_data->sender_id == node->known_id) { node->neighborhood_set[0] = task_data->sender_id; for (i=1; i<NEIGHBORHOOD_SIZE; i++) node->neighborhood_set[i] = task_data->state->neighborhood_set[i-1]; } // copy the corresponding routing table levels min = (node->id==task_data->answer_id) ? 0 : shl(node->id, task_data->answer_id); max = shl(node->id, task_data->sender_id)+1; for (i=min;i<max;i++) { d = domain(node->id, i); for (j=0; j<LEVEL_SIZE; j++) if (d!=j) node->routing_table[i][j] = task_data->state->routing_table[i][j]; } node->ready--; // if the node is ready, do all the pending tasks and send update to known nodes if (node->ready==0) { XBT_DEBUG("Node %i is ready!!!", node->id); while(xbt_fifo_size(node->pending_tasks)) handle_task(node, xbt_fifo_pop(node->pending_tasks)); for (i=0; i<NAMESPACE_SIZE; i++) { j = node->namespace_set[i]; if (j!=-1) { XBT_DEBUG("Send update to %i", j); get_mailbox(j, mailbox); req_data = xbt_new0(s_task_data_t,1); req_data->answer_id = node->id; req_data->steps = 0; req_data->type = TASK_UPDATE; req_data->sender_id = node->id; get_mailbox(node->id, req_data->answer_to); req_data->state = node_get_state(node); task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data); MSG_task_send_with_timeout(task_sent, mailbox, timeout); } } } break; /* * Recieved an update of state */ case TASK_UPDATE: XBT_DEBUG("Task update %i !!!", node->id); /* Update namespace ses */ printf("Task update from %i !!!\n", task_data->sender_id); print_node_id(node); print_node_namespace_set(node); int curr_namespace_set[NAMESPACE_SIZE]; int task_namespace_set[NAMESPACE_SIZE+1]; // Copy the current namedspace // and the task state namespace with state->id in the middle i=0; for (; i<NAMESPACE_SIZE/2; i++){ curr_namespace_set[i] = node->namespace_set[i]; task_namespace_set[i] = task_data->state->namespace_set[i]; } task_namespace_set[i] = task_data->state->id; for (; i<NAMESPACE_SIZE; i++){ curr_namespace_set[i] = node->namespace_set[i]; task_namespace_set[i+1] = task_data->state->namespace_set[i]; } // get the index of values before and after node->id in task_namespace min = -1; max = -1; for (i=0; i<=NAMESPACE_SIZE; i++) { j = task_namespace_set[i]; if (i<NAMESPACE_SIZE) printf("%08x %08x | ", j, curr_namespace_set[i]); if (j != -1 && j < node->id) min = i; if (j != -1 && max == -1 && j > node->id) max = i; } printf("\n"); // add lower elements j = NAMESPACE_SIZE/2-1; for (i=NAMESPACE_SIZE/2-1; i>=0; i--) { printf("i:%i, j:%i, min:%i, currj:%08x, taskmin:%08x\n", i, j, min, curr_namespace_set[j], task_namespace_set[min]); if (min<0) { node->namespace_set[i] = curr_namespace_set[j]; j--; } else if (curr_namespace_set[j] == task_namespace_set[min]) { node->namespace_set[i] = curr_namespace_set[j]; j--; min--; } else if (curr_namespace_set[j] > task_namespace_set[min]) { node->namespace_set[i] = curr_namespace_set[j]; j--; } else { node->namespace_set[i] = task_namespace_set[min]; min--; } } // add greater elements j = NAMESPACE_SIZE/2; for (i=NAMESPACE_SIZE/2; i<NAMESPACE_SIZE; i++) { printf("i:%i, j:%i, max:%i, currj:%08x, taskmax:%08x\n", i, j, max, curr_namespace_set[j], task_namespace_set[max]); if (min<0 || max>=NAMESPACE_SIZE) { node->namespace_set[i] = curr_namespace_set[j]; j++; } else if (curr_namespace_set[j] == -1) { node->namespace_set[i] = task_namespace_set[max]; max++; } else if (curr_namespace_set[j] == task_namespace_set[max]) { node->namespace_set[i] = curr_namespace_set[j]; j++; max++; } else if (curr_namespace_set[j] < task_namespace_set[max]) { node->namespace_set[i] = curr_namespace_set[j]; j++; } else { node->namespace_set[i] = task_namespace_set[max]; max++; } } print_node_namespace_set(node); /* Update routing table */ for (i=shl(node->id, task_data->state->id); i<LEVELS_COUNT; i++) { for (j=0; j<LEVEL_SIZE; j++) { if (node->routing_table[i][j]==-1 && task_data->state->routing_table[i][j]==-1) node->routing_table[i][j] = task_data->state->routing_table[i][j]; } } } }
/** Handle a given task */ static void handle_task(node_t node, msg_task_t task) { XBT_DEBUG("Handling task %p", task); char mailbox[MAILBOX_NAME_SIZE]; int i; int j; int min; int max; int next; msg_task_t task_sent; task_data_t req_data; task_data_t task_data = (task_data_t) MSG_task_get_data(task); e_task_type_t type = task_data->type; // If the node is not ready keep the task for later if (node->ready != 0 && !(type==TASK_JOIN_LAST_REPLY || type==TASK_JOIN_REPLY)) { XBT_DEBUG("Task pending %u", type); xbt_dynar_push(node->pending_tasks, &task); return; } switch (type) { /* Try to join the ring */ case TASK_JOIN: next = routing_next(node, task_data->answer_id); XBT_DEBUG("Join request from %08x forwarding to %08x", (unsigned)task_data->answer_id, (unsigned)next); type = TASK_JOIN_LAST_REPLY; req_data = xbt_new0(s_task_data_t,1); req_data->answer_id = task_data->sender_id; req_data->steps = task_data->steps + 1; // if next different from current node forward the join if (next!=node->id) { get_mailbox(next, mailbox); task_data->sender_id = node->id; task_data->steps++; task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, task_data); if (MSG_task_send_with_timeout(task_sent, mailbox, timeout)== MSG_TIMEOUT) { XBT_DEBUG("Timeout expired when forwarding join to next %d", next); task_free(task_sent); } type = TASK_JOIN_REPLY; } // send back the current node state to the joining node req_data->type = type; req_data->sender_id = node->id; get_mailbox(node->id, req_data->answer_to); req_data->state = node_get_state(node); task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data); if (MSG_task_send_with_timeout(task_sent, task_data->answer_to, timeout)== MSG_TIMEOUT) { XBT_DEBUG("Timeout expired when sending back the current node state to the joining node to %d", node->id); task_free(task_sent); } break; /* Join reply from all the node touched by the join */ case TASK_JOIN_LAST_REPLY: // if last node touched reply, copy its namespace set // TODO: it works only if the two nodes are side to side (is it really the case ?) j = (task_data->sender_id < node->id) ? -1 : 0; for (i=0; i<NAMESPACE_SIZE/2; i++) { node->namespace_set[i] = task_data->state->namespace_set[i-j]; node->namespace_set[NAMESPACE_SIZE-1-i] = task_data->state->namespace_set[NAMESPACE_SIZE-1-i-j-1]; } node->namespace_set[NAMESPACE_SIZE/2+j] = task_data->sender_id; node->ready += task_data->steps + 1; /* no break */ case TASK_JOIN_REPLY: XBT_DEBUG("Joining Reply"); // if first node touched reply, copy its neighborhood set if (task_data->sender_id == node->known_id) { node->neighborhood_set[0] = task_data->sender_id; for (i=1; i<NEIGHBORHOOD_SIZE; i++) node->neighborhood_set[i] = task_data->state->neighborhood_set[i-1]; } // copy the corresponding routing table levels min = (node->id==task_data->answer_id) ? 0 : shl(node->id, task_data->answer_id); max = shl(node->id, task_data->sender_id)+1; for (i=min;i<max;i++) { int d = domain(node->id, i); for (j=0; j<LEVEL_SIZE; j++) if (d!=j) node->routing_table[i][j] = task_data->state->routing_table[i][j]; } node->ready--; // if the node is ready, do all the pending tasks and send update to known nodes if (node->ready==0) { XBT_DEBUG("Node %i is ready!!!", node->id); while (!xbt_dynar_is_empty(node->pending_tasks)) { msg_task_t task; xbt_dynar_shift(node->pending_tasks, &task); handle_task(node, task); } for (i=0; i<NAMESPACE_SIZE; i++) { j = node->namespace_set[i]; if (j!=-1) { XBT_DEBUG("Send update to %i", j); get_mailbox(j, mailbox); req_data = xbt_new0(s_task_data_t,1); req_data->answer_id = node->id; req_data->steps = 0; req_data->type = TASK_UPDATE; req_data->sender_id = node->id; get_mailbox(node->id, req_data->answer_to); req_data->state = node_get_state(node); task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data); if (MSG_task_send_with_timeout(task_sent, mailbox, timeout)== MSG_TIMEOUT) { XBT_DEBUG("Timeout expired when sending update to %d", j); task_free(task_sent); } } } } break; /* Received an update of state */ case TASK_UPDATE: XBT_DEBUG("Task update %i !!!", node->id); /* Update namespace ses */ XBT_INFO("Task update from %i !!!", task_data->sender_id); XBT_INFO("Node:"); print_node_id(node); print_node_namespace_set(node); int curr_namespace_set[NAMESPACE_SIZE]; int task_namespace_set[NAMESPACE_SIZE+1]; // Copy the current namespace and the task state namespace with state->id in the middle i=0; for (; i<NAMESPACE_SIZE/2; i++){ curr_namespace_set[i] = node->namespace_set[i]; task_namespace_set[i] = task_data->state->namespace_set[i]; } task_namespace_set[i] = task_data->state->id; for (; i<NAMESPACE_SIZE; i++){ curr_namespace_set[i] = node->namespace_set[i]; task_namespace_set[i+1] = task_data->state->namespace_set[i]; } // get the index of values before and after node->id in task_namespace min = -1; max = -1; for (i=0; i<=NAMESPACE_SIZE; i++) { j = task_namespace_set[i]; if (j != -1 && j < node->id) min = i; if (j != -1 && max == -1 && j > node->id) max = i; } // add lower elements j = NAMESPACE_SIZE/2-1; for (i=NAMESPACE_SIZE/2-1; i>=0; i--) { if (min < 0 || curr_namespace_set[j] > task_namespace_set[min]) { node->namespace_set[i] = curr_namespace_set[j]; j--; } else if (curr_namespace_set[j] == task_namespace_set[min]) { node->namespace_set[i] = curr_namespace_set[j]; j--; min--; } else { node->namespace_set[i] = task_namespace_set[min]; min--; } } // add greater elements j = NAMESPACE_SIZE/2; for (i=NAMESPACE_SIZE/2; i<NAMESPACE_SIZE; i++) { if (min<0 || max>=NAMESPACE_SIZE) { node->namespace_set[i] = curr_namespace_set[j]; j++; } else if (max >= 0){ if (curr_namespace_set[j] == -1 || curr_namespace_set[j] > task_namespace_set[max]) { node->namespace_set[i] = task_namespace_set[max]; max++; } else if (curr_namespace_set[j] == task_namespace_set[max]) { node->namespace_set[i] = curr_namespace_set[j]; j++; max++; } else { node->namespace_set[i] = curr_namespace_set[j]; j++; } } } /* Update routing table */ for (i=shl(node->id, task_data->state->id); i<LEVELS_COUNT; i++) { for (j=0; j<LEVEL_SIZE; j++) { if (node->routing_table[i][j]==-1 && task_data->state->routing_table[i][j]==-1) node->routing_table[i][j] = task_data->state->routing_table[i][j]; } } break; default: THROW_IMPOSSIBLE; } task_free(task); }