/* cmd_fg() function. * with no arguments, it just put the latest bg job back; * with one argument, it put the process with the input * job number back. */ int cmd_fg(int argc, char** argv) { if (argc > 2) { printf("Shell: fg: too many arguments!\n"); return SYNTAX_ERROR; } else if (argc == 2) { if (atoi(argv[1]) > bg_top + 1) { printf("Shell: fg: no such job!\n"); return OTHER_ERROR; } else { int i = atoi(argv[1]) - 1; pid_t to_call = bg_list[i].pid; if (pid_exist(to_call)) { /* start to wait for the process */ bg_remove(i); setpgid(to_call, getpgrp()); if (waitpid(to_call, 0, 0) < 0) { printf("Shell: error: waitpid error!\n"); return OTHER_ERROR; } return NORMAL; } /* the process already somehow quit */ else { printf("[ %d ] pid = %d Done.\n", i+1, to_call); return NORMAL; } } } else if (argc == 1) { if (bg_top == -1) { printf("Shell: no background jobs!\n"); return OTHER_ERROR; } else { pid_t to_call = bg_list[bg_top].pid; if (pid_exist(to_call)) { /* start to wait for the process */ bg_remove(bg_top); if (waitpid(to_call, 0, 0) < 0) { printf("Shell: error: waitpid error!\n"); return OTHER_ERROR; } return NORMAL; } /* the process already somehow quit */ else { printf("[ %d ] pid = %d Done.\n", bg_top+1, to_call); return NORMAL; } } } }
/* check each pid's status in the bg list */ void bg_checkall(void) { //debug information //printf("debug: in bg_checkall() function\n"); int i; if (bg_top == -1) return; for (i = 0; i <= bg_top; i++) { if ( waitpid(bg_list[i].pid, 0, WNOHANG) < 0) { printf("[ %d ] pid = %d Done.\n", i, bg_list[i].pid); bg_remove(i); } } }
/** * bg_trav_nodes - traverse node level of skip list and maintain * @ptst: per-thread state * * Note: this will try to remove each of the nodes in the list, * in order to extract nodes that have already been logically deleted * but that are still accessible. */ static void bg_trav_nodes(ptst_t *ptst) { node_t *prev, *node; assert(NULL != set && NULL != set->head); prev = set->head; node = prev->next; while (NULL != node) { bg_remove(prev, node, ptst); if (NULL != node->val && node != node->val) ++bg_non_deleted; else if (node->level >= 1) ++bg_tall_deleted; prev = node; node = node->next; } }
/** * bg_trav_nodes - traverse node level of skip list * @ptst: per-thread state * * Returns 1 if a raise was done and 0 otherwise. * * Note: this tries to raise non-deleted nodes, and finished deletions that * have been started but not completed. */ static int bg_trav_nodes(ptst_t *ptst) { node_t *prev, *node, *next; node_t *above_head = set->head, *above_prev, *above_next; unsigned long zero = sl_zero; int raised = 0; assert(NULL != set && NULL != set->head); ptst = ptst_critical_enter(); above_prev = above_next = above_head; prev = set->head; node = prev->next; if (NULL == node) return 0; next = node->next; while (NULL != next) { if (NULL == node->val) { bg_remove(prev, node, ptst); if (node->level >= 1) ++bg_tall_deleted; ++bg_deleted; } else if (node->val != node) { if ((((0 == prev->level && 0 == node->level) && 0 == next->level)) && CAS(&node->raise_or_remove, 0, 1)) { node->level = 1; raised = 1; get_index_above(above_head, &above_prev, &above_next, 0, node->key, zero); // swap the pointers node->succs[IDX(0,zero)] = above_next; BARRIER(); // make sure above happens first above_prev->succs[IDX(0,zero)] = node; above_next = above_prev = above_head = node; } } if (NULL != node->val && node != node->val) { ++bg_non_deleted; } prev = node; node = next; next = next->next; } ptst_critical_exit(ptst); return raised; }