Пример #1
0
Файл: Q.cpp Проект: tomerd/q
 bool Q::cancel(const string& uid)
 {
     JobOption job = find_job(uid);
     if (job.empty()) return false;
     delete_job(job.get().uid());
     return true;
 }
Пример #2
0
int preempt(job_t* job)
{
	int cmp_n, cmp = 0;
	int i, x = -1;
	for ( i=0; i < cores.cnt; i++ )
	{
		cmp_n = sch_time(job, cores.jobs[i]);
		if ( cmp_n < cmp )
		{
			cmp = cmp_n;
			x = i;
		}//if
		else if ( cmp_n == cmp )
		{
			if ( x != -1 && cores.jobs[x]->arr_t < cores.jobs[i]->arr_t )
				x = i;
		}//else if
	}//for

	// insert job into core list.
	if ( x >= 0 )
	{
		delete_job(x,cores.jobs[x]->jid);
		insert_job(x,job);
	}//if

	return x;
}//preempt
Пример #3
0
static PRJob *
alloc_job(PRBool joinable, PRThreadPool *tp)
{
	PRJob *jobp;

	jobp = PR_NEWZAP(PRJob);
	if (NULL == jobp) 
		goto failed;
	if (joinable) {
		jobp->join_cv = PR_NewCondVar(tp->join_lock);
		jobp->join_wait = PR_TRUE;
		if (NULL == jobp->join_cv)
			goto failed;
	} else {
		jobp->join_cv = NULL;
	}
#ifdef OPT_WINNT
	jobp->nt_notifier.jobp = jobp;
#endif
	return jobp;
failed:
	delete_job(jobp);
	PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
	return NULL;
}
Пример #4
0
void fgCommand(int index) {
	int size = list_size(lista_trabajos);	// Guardamos el tamaño de la lista

	if(empty_list(lista_trabajos)) {
		printf("La lista está vacía\n");
	} else if(index > size || index <= 0) {
		printf("El argumento indicado está fuera del rango de la lista\n");
		printf("La lista sólo contiene {%d} elementos\n", size);
	} else {

		// Extraemos el trabajo de la lista de trabajos
		job *trabajo = get_item_bypos(lista_trabajos, index);

		// Información sobre el proceso actual
		printf("Tarea: %d, pid: %d, comando: %s, estado anterior: %s. \n", index, trabajo->pgid, trabajo->command, state_strings[trabajo->state]);

		// Si la tarea está parada es que la hemos suspendido
		if(trabajo->state == STOPPED) {
			printf("Reanudando la tarea... \n");
			killpg(trabajo->pgid, SIGCONT);		// Enviamos al proceso la señal para reanudarlo
		}

		if(trabajo->state != FOREGROUND) {
			int status;
			int pgid;
			int info;
			pgid = trabajo->pgid;
			trabajo->state = FOREGROUND;

			printf("Tarea: %d, pid: %d, comando: %s, estado actual: %s. \n", index, trabajo->pgid, trabajo->command, state_strings[trabajo->state]);
			printf("Asignándole el terminal...\n");

			set_terminal(pgid);
			// Esperamos que el proceso siga haciendo su ejecución en primer plano
			pid_t wpid = waitpid(pgid, &status, WUNTRACED);

			// Vemos su nuevo estado y damos el mensaje
			enum status st = analyze_status(status, &info);
			printf("Background pid: %d, command: %s, %s, info: %d \n", wpid, trabajo->command, status_strings[st], info);

			block_SIGCHLD();

			if(st == SUSPENDED) {
				// Actualizamos su estado en la lista
				trabajo->state = STOPPED;
			// Si no, es que ha terminado y por tanto lo eliminamos de la lista
			} else {
				// Lo eliminamos de la lista
				delete_job(lista_trabajos, trabajo);
			}

			unblock_SIGCHLD();

			// Le devolvemos al terminal al proceso principal
			set_terminal(getpid());
		}
	}
}
Пример #5
0
/** Manejador para la señal SIGCHLD **/
void manejador(int senal) {
	int i;

	// Recorremos la lista
	for(i = list_size(lista_trabajos); i >= 1; i--) {

		// Extraemos un trabajo
		job *aux = get_item_bypos(lista_trabajos, i);

		// Si no es de foreground, es decir BACKGROUND O STOPPED
		if(aux->state != FOREGROUND) {
			int status;

			// Vemos si ha cambiado su estado sin bloquearnos (Wait no bloqueante)
			// es totalmente necesario WNOHANG para no quedarnos bloqueados
			pid_t wpid = waitpid(aux->pgid, &status, WNOHANG | WUNTRACED);

			// Si es el caso
			if(wpid == aux->pgid) {
				int info;

				// Vemos su nuevo estado y damos el mensaje
				enum status st = analyze_status(status, &info);
				printf("Background pid: %d, command: %s, %s, info: %d \n", wpid, aux->command, status_strings[st], info);

				// Si se ha suspendido
				if(st == SUSPENDED) {
					// Actualizamos su estado en la lista
					aux->state = STOPPED;

                // Si no, se trata de un proceso terminado
				} else {

                    if(aux->state == RESPAWNABLE) {

                        // Restauramos las señales que reciben del terminal
                        restore_terminal_signals();

                        aux->args[0] = "#";

                        // Volvemos a ejecutar el comando
                        execvp(aux->command, aux->args);

                        // Solo llegará aquí si no se ha producido el cambio de imagen
                        printf("Error. No se ha podido hacer el respawn: %s\n", aux->command);
                        exit(-1);
                    }

                    // Lo eliminamos de la lista
                    delete_job(lista_trabajos, aux);
				}
			}
		}
	}
}
Пример #6
0
void print_all_job(void)
{
        int i;
        for (i = beg; i < end; i++) {
                if (!job[i])
                        continue;
                print_job(i);
                if (job[i]->state == JOB_DONE)
                        delete_job(job[i]->pgid);
        }
}
Пример #7
0
PR_JoinJob(PRJob *jobp)
{
	if (!JOINABLE_JOB(jobp)) {
		PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
		return PR_FAILURE;
	}
	PR_Lock(jobp->tpool->join_lock);
	while(jobp->join_wait)
		PR_WaitCondVar(jobp->join_cv, PR_INTERVAL_NO_TIMEOUT);
	PR_Unlock(jobp->tpool->join_lock);
	delete_job(jobp);
	return PR_SUCCESS;
}
Пример #8
0
Файл: Q.cpp Проект: tomerd/q
 const string Q::post(const string& queue_name, const string& uid, const string& data, const long run_at)
 {
     if (!this->active) return "";
     
     if (!uid.empty())
     {
         JobOption existing = find_job(uid);
         if (!existing.empty()) delete_job(uid);
     }
     
     Job job = Job(uid, data, JSPending, run_at);
     push_back(queue_name, job);
     q_log("posted [%s] on [%s] as [%s]", data.c_str(), queue_name.c_str(), job.uid().c_str());
     return job.uid();
 }
Пример #9
0
/**
	When the scheme is set to RR, called when the quantum timer has expired
	on a core.
 
	If any job should be scheduled to run on the core free'd up by
	the quantum expiration, return the job_number of the job that should be
	scheduled to run on core core_id.
	@param core_id the zero-based index of the core where the quantum has expired.
	@param time the current time of the simulator. 
	@return job_number of the job that should be scheduled on core cord_id
	@return -1 if core should remain idle
 */
int scheduler_quantum_expired(int core_id, int time)
{
	// Increment Time
	inc_time(time);

	// Process quantumn rollover
	delete_job(core_id,cores.jobs[core_id]->jid);
	
	// Schedule new job
	job_t* p = priqueue_poll(jobs);
	if ( p != NULL )
	{
		insert_job(core_id,p);
		return p->jid;
	}//if
	return -1;
}//scheduler_quantum_expired
Пример #10
0
static void* thr_fn(void *arg) {
    struct worker_t *w = (struct worker_t*)arg;
    struct job_t job;
    unsigned int sleep_time = 0, slept_time;
    time_t start, now;
    char now_str[128], ap_str[128];
    struct tm now_tm, ap_tm;
    sigset_t mask;

    sigfillset(&mask);
    sigdelset(&mask, SIG_WORKER_INTERRUPT);
    sigdelset(&mask, SIG_WORKER_KILL);
    pthread_sigmask(SIG_BLOCK, &mask, NULL);

    while (!__sync_fetch_and_add(&w->exit_loop, 0)) {
        start = time(NULL);
        do {
            if (sleep_time == 0)
                sleep_time = w->interval;
            next_job(w, &job, &sleep_time);
            if (job.id > 0)
                w->wlog("next job[%d] start in %d seconds\n", job.id, sleep_time);
            sleep_time = sleep(sleep_time);
            if (sleep_time > 0)
                w->wlog("interrupt by signal, %d seconds left\n", sleep_time);
        }
        while (sleep_time > 0);

        now = time(NULL);
        slept_time = now - start;
        strftime(now_str, 128, "%T", localtime_r(&now, &now_tm));
        if (job.id > 0) {
            strftime(ap_str, 128, "%T", localtime_r(&job.ap_time, &ap_tm));
            w->wlog("[%s] do job[%d], appointment time[%s], slept %d seconds\n",
                    now_str, job.id, ap_str, slept_time);
            delete_job(w, job.id);
        } else {
            w->wlog("[%s] slept %d seconds\n", now_str, slept_time);
        }
    }

    return NULL;
}
Пример #11
0
/**
	Called when a job has completed execution.
 
	The core_id, job_number and time parameters are provided for convenience. You may be able to calculate the values with your own data structure.
	If any job should be scheduled to run on the core free'd up by the
	finished job, return the job_number of the job that should be scheduled to
	run on core core_id.
 
	@param core_id the zero-based index of the core where the job was located.
	@param job_number a globally unique identification number of the job.
	@param time the current time of the simulator.
	@return job_number of the job that should be scheduled to run on core core_id
	@return -1 if core should remain idle.
 */
int scheduler_job_finished(int core_id, int job_number, int time)
{
	// Increment Time
	inc_time(time);

	// Process job termination
	job_t* p = delete_job(core_id,job_number);
	priqueue_remove(jobs,p);
	inc_wait(cur_t - p->arr_t - p->run_t);
	inc_turn(cur_t - p->arr_t);
	free_job(p);
	
	// Schedule new job
	p = priqueue_poll(jobs);
	if ( p != NULL )
	{
		insert_job(core_id,p);
		return p->jid;
	}//if
	return -1;
}//scheduler_job_finished
Пример #12
0
// handler for all of the signals (SIGCHLD, SIGINT, SIGTSTP)
void child_signal_handler(int signum, siginfo_t* siginfo, void* extra){

  if(signum == SIGCHLD){
    int status, ch_pid;
    ch_pid = waitpid(-1, &status, WNOHANG | WUNTRACED | WCONTINUED);

    if(ch_pid > 0){

      if(ch_pid == pipe_pid){
        pipe_pid = 0;
      }
      //find which subjob(process) and which job this child process belongs to.
      job* this_job = find_job_pid(ch_pid, jlist);
      subjob* this_subjob = find_subjob(this_job, ch_pid);

      //handle each case of status change
      if(WIFEXITED(status)){
        this_subjob->finished = 1; // if subjob exited normally

        if(job_finished(this_job)){

          if(ch_pid == fg_pid){
            fg_pid = 0; // if child process exited is a foreground job, reset

            if(tcsetpgrp(STDIN_FILENO, getpgid(0)) == -1){
              perror("tcsetpgrp error 1");
            }
          }
          else{ //if ch_pid was a background job
            message_q = add(message_q, "\n");
            message_q = add(message_q, this_job->command);
            message_q = add(message_q, "Finished: ");
          }
          delete_job(this_job, jlist);
        }
      }
      else if(WIFSIGNALED(status)){

        if(ch_pid == fg_pid){
          fg_pid = 0;

          if(tcsetpgrp(STDIN_FILENO, getpgid(0)) == -1){
            perror("tcsetpgrp error");
          }
        }
        delete_job(this_job, jlist); //delete corresponding job
      }
      else if(WIFSTOPPED(status)){

        if(ch_pid == fg_pid){
          fg_pid = 0;

          if(tcsetpgrp(STDIN_FILENO, getpgid(ch_pid)) == -1){
            perror("tcsetpgrp error 3");
          }
        }
        this_subjob->stopped = 1; // set the stopped boolean to TRUE

        if(job_stopped(this_job)){
          message_q = add(message_q, "\n"); // add stopped prompt to message q
          message_q = add(message_q, this_job->command);
          message_q = add(message_q, "Stopped: ");
          update_orders(jlist, this_job); // update ranking of most recent jobs 
        }
      }

      else if(WIFCONTINUED(status)){//restart the stopped process
        this_subjob->stopped = 0;

        if(!job_stopped(this_job)){
         update_orders(jlist, this_job); // update order of jobs in job_list
        }

        if(fg_pid){
          if(tcsetpgrp(STDIN_FILENO, fg_pid) == -1){
            perror("tcsetpgrp error 5");
          }
        }
        else{

        }

      }
      ch_pid = waitpid(-1, &status, WNOHANG | WUNTRACED | WCONTINUED); // wait
    }
  }
  if(signum == SIGINT){
    //ctrl-C
    //if the signal is coming from the main shell, exit the shell.
    if(sh_pgid == getpgid(siginfo->si_pid)){

      if(fg_pid){
        killpg(getpgid(fg_pid), SIGINT); // kill fg process with SIGINT
      }
    }
    else{
      killpg(0, SIGTERM);
    }
  }

  if(signum == SIGTSTP){

    if(sh_pgid == getpgid(siginfo->si_pid)){

      if(fg_pid){
        killpg(getpgid(fg_pid), SIGTSTP); // kill fg process with SIGTSTP
      }
    }
    else{
      killpg(0, SIGSTOP);
    } 
  }
}
Пример #13
0
PR_CancelJob(PRJob *jobp) {

	PRStatus rval = PR_FAILURE;
	PRThreadPool *tp;

	if (jobp->on_timerq) {
		/*
		 * now, check again while holding the timerq lock
		 */
		tp = jobp->tpool;
		PR_Lock(tp->timerq.lock);
		if (jobp->on_timerq) {
			jobp->on_timerq = PR_FALSE;
			PR_REMOVE_AND_INIT_LINK(&jobp->links);
			tp->timerq.cnt--;
			PR_Unlock(tp->timerq.lock);
			if (!JOINABLE_JOB(jobp)) {
				delete_job(jobp);
			} else {
				JOIN_NOTIFY(jobp);
			}
			rval = PR_SUCCESS;
		} else
			PR_Unlock(tp->timerq.lock);
	} else if (jobp->on_ioq) {
		/*
		 * now, check again while holding the ioq lock
		 */
		tp = jobp->tpool;
		PR_Lock(tp->ioq.lock);
		if (jobp->on_ioq) {
			jobp->cancel_cv = PR_NewCondVar(tp->ioq.lock);
			if (NULL == jobp->cancel_cv) {
				PR_Unlock(tp->ioq.lock);
				PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
				return PR_FAILURE;
			}
			/*
			 * mark job 'cancelled' and notify io thread(s)
			 * XXXX:
			 *		this assumes there is only one io thread; when there
			 * 		are multiple threads, the io thread processing this job
			 * 		must be notified.
			 */
			jobp->cancel_io = PR_TRUE;
			PR_Unlock(tp->ioq.lock);	/* release, reacquire ioq lock */
			notify_ioq(tp);
			PR_Lock(tp->ioq.lock);
			while (jobp->cancel_io)
				PR_WaitCondVar(jobp->cancel_cv, PR_INTERVAL_NO_TIMEOUT);
			PR_Unlock(tp->ioq.lock);
			PR_ASSERT(!jobp->on_ioq);
			if (!JOINABLE_JOB(jobp)) {
				delete_job(jobp);
			} else {
				JOIN_NOTIFY(jobp);
			}
			rval = PR_SUCCESS;
		} else
			PR_Unlock(tp->ioq.lock);
	}
	if (PR_FAILURE == rval)
		PR_SetError(PR_INVALID_STATE_ERROR, 0);
	return rval;
}
Пример #14
0
/* queue a job, when a socket is readable or writeable */
static PRJob *
queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg,
				PRBool joinable, io_op_type op)
{
	PRJob *jobp;
	PRIntervalTime now;

	jobp = alloc_job(joinable, tpool);
	if (NULL == jobp) {
		return NULL;
	}

	/*
	 * Add a new job to io_jobq
	 * wakeup io worker thread
	 */

	jobp->job_func = fn;
	jobp->job_arg = arg;
	jobp->tpool = tpool;
	jobp->iod = iod;
	if (JOB_IO_READ == op) {
		jobp->io_op = JOB_IO_READ;
		jobp->io_poll_flags = PR_POLL_READ;
	} else if (JOB_IO_WRITE == op) {
		jobp->io_op = JOB_IO_WRITE;
		jobp->io_poll_flags = PR_POLL_WRITE;
	} else if (JOB_IO_ACCEPT == op) {
		jobp->io_op = JOB_IO_ACCEPT;
		jobp->io_poll_flags = PR_POLL_READ;
	} else if (JOB_IO_CONNECT == op) {
		jobp->io_op = JOB_IO_CONNECT;
		jobp->io_poll_flags = PR_POLL_WRITE|PR_POLL_EXCEPT;
	} else {
		delete_job(jobp);
		PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
		return NULL;
	}

	jobp->timeout = iod->timeout;
	if ((PR_INTERVAL_NO_TIMEOUT == iod->timeout) ||
			(PR_INTERVAL_NO_WAIT == iod->timeout)) {
		jobp->absolute = iod->timeout;
	} else {
		now = PR_IntervalNow();
		jobp->absolute = now + iod->timeout;
	}


	PR_Lock(tpool->ioq.lock);

	if (PR_CLIST_IS_EMPTY(&tpool->ioq.list) ||
			(PR_INTERVAL_NO_TIMEOUT == iod->timeout)) {
		PR_APPEND_LINK(&jobp->links,&tpool->ioq.list);
	} else if (PR_INTERVAL_NO_WAIT == iod->timeout) {
		PR_INSERT_LINK(&jobp->links,&tpool->ioq.list);
	} else {
		PRCList *qp;
		PRJob *tmp_jobp;
		/*
		 * insert into the timeout-sorted ioq
		 */
		for (qp = tpool->ioq.list.prev; qp != &tpool->ioq.list;
							qp = qp->prev) {
			tmp_jobp = JOB_LINKS_PTR(qp);
			if ((PRInt32)(jobp->absolute - tmp_jobp->absolute) >= 0) {
				break;
			}
		}
		PR_INSERT_AFTER(&jobp->links,qp);
	}

	jobp->on_ioq = PR_TRUE;
	tpool->ioq.cnt++;
	/*
	 * notify io worker thread(s)
	 */
	PR_Unlock(tpool->ioq.lock);
	notify_ioq(tpool);
	return jobp;
}
Пример #15
0
/*
 * worker thread function
 */
static void wstart(void *arg)
{
PRThreadPool *tp = (PRThreadPool *) arg;
PRCList *head;

	/*
	 * execute jobs until shutdown
	 */
	while (!tp->shutdown) {
		PRJob *jobp;
#ifdef OPT_WINNT
		BOOL rv;
		DWORD unused, shutdown;
		LPOVERLAPPED olp;

		PR_Lock(tp->jobq.lock);
		tp->idle_threads++;
		PR_Unlock(tp->jobq.lock);
		rv = GetQueuedCompletionStatus(tp->jobq.nt_completion_port,
					&unused, &shutdown, &olp, INFINITE);
		
		PR_ASSERT(rv);
		if (shutdown)
			break;
		jobp = ((NT_notifier *) olp)->jobp;
		PR_Lock(tp->jobq.lock);
		tp->idle_threads--;
		tp->jobq.cnt--;
		PR_Unlock(tp->jobq.lock);
#else

		PR_Lock(tp->jobq.lock);
		while (PR_CLIST_IS_EMPTY(&tp->jobq.list) && (!tp->shutdown)) {
			tp->idle_threads++;
			PR_WaitCondVar(tp->jobq.cv, PR_INTERVAL_NO_TIMEOUT);
			tp->idle_threads--;
		}	
		if (tp->shutdown) {
			PR_Unlock(tp->jobq.lock);
			break;
		}
		head = PR_LIST_HEAD(&tp->jobq.list);
		/*
		 * remove job from queue
		 */
		PR_REMOVE_AND_INIT_LINK(head);
		tp->jobq.cnt--;
		jobp = JOB_LINKS_PTR(head);
		PR_Unlock(tp->jobq.lock);
#endif

		jobp->job_func(jobp->job_arg);
		if (!JOINABLE_JOB(jobp)) {
			delete_job(jobp);
		} else {
			JOIN_NOTIFY(jobp);
		}
	}
	PR_Lock(tp->jobq.lock);
	tp->current_threads--;
	PR_Unlock(tp->jobq.lock);
}
Пример #16
0
PR_JoinThreadPool(PRThreadPool *tpool)
{
PRStatus rval = PR_SUCCESS;
PRCList *head;
PRStatus rval_status;

	PR_Lock(tpool->jobq.lock);
	while (!tpool->shutdown)
		PR_WaitCondVar(tpool->shutdown_cv, PR_INTERVAL_NO_TIMEOUT);

	/*
	 * wakeup worker threads
	 */
#ifdef OPT_WINNT
	/*
	 * post shutdown notification for all threads
	 */
	{
		int i;
		for(i=0; i < tpool->current_threads; i++) {
			PostQueuedCompletionStatus(tpool->jobq.nt_completion_port, 0,
												TRUE, NULL);
		}
	}
#else
	PR_NotifyAllCondVar(tpool->jobq.cv);
#endif

	/*
	 * wakeup io thread(s)
	 */
	notify_ioq(tpool);

	/*
	 * wakeup timer thread(s)
	 */
	PR_Lock(tpool->timerq.lock);
	notify_timerq(tpool);
	PR_Unlock(tpool->timerq.lock);

	while (!PR_CLIST_IS_EMPTY(&tpool->jobq.wthreads)) {
		wthread *wthrp;

		head = PR_LIST_HEAD(&tpool->jobq.wthreads);
		PR_REMOVE_AND_INIT_LINK(head);
		PR_Unlock(tpool->jobq.lock);
		wthrp = WTHREAD_LINKS_PTR(head);
		rval_status = PR_JoinThread(wthrp->thread);
		PR_ASSERT(PR_SUCCESS == rval_status);
		PR_DELETE(wthrp);
		PR_Lock(tpool->jobq.lock);
	}
	PR_Unlock(tpool->jobq.lock);
	while (!PR_CLIST_IS_EMPTY(&tpool->ioq.wthreads)) {
		wthread *wthrp;

		head = PR_LIST_HEAD(&tpool->ioq.wthreads);
		PR_REMOVE_AND_INIT_LINK(head);
		wthrp = WTHREAD_LINKS_PTR(head);
		rval_status = PR_JoinThread(wthrp->thread);
		PR_ASSERT(PR_SUCCESS == rval_status);
		PR_DELETE(wthrp);
	}

	while (!PR_CLIST_IS_EMPTY(&tpool->timerq.wthreads)) {
		wthread *wthrp;

		head = PR_LIST_HEAD(&tpool->timerq.wthreads);
		PR_REMOVE_AND_INIT_LINK(head);
		wthrp = WTHREAD_LINKS_PTR(head);
		rval_status = PR_JoinThread(wthrp->thread);
		PR_ASSERT(PR_SUCCESS == rval_status);
		PR_DELETE(wthrp);
	}

	/*
	 * Delete queued jobs
	 */
	while (!PR_CLIST_IS_EMPTY(&tpool->jobq.list)) {
		PRJob *jobp;

		head = PR_LIST_HEAD(&tpool->jobq.list);
		PR_REMOVE_AND_INIT_LINK(head);
		jobp = JOB_LINKS_PTR(head);
		tpool->jobq.cnt--;
		delete_job(jobp);
	}

	/* delete io jobs */
	while (!PR_CLIST_IS_EMPTY(&tpool->ioq.list)) {
		PRJob *jobp;

		head = PR_LIST_HEAD(&tpool->ioq.list);
		PR_REMOVE_AND_INIT_LINK(head);
		tpool->ioq.cnt--;
		jobp = JOB_LINKS_PTR(head);
		delete_job(jobp);
	}

	/* delete timer jobs */
	while (!PR_CLIST_IS_EMPTY(&tpool->timerq.list)) {
		PRJob *jobp;

		head = PR_LIST_HEAD(&tpool->timerq.list);
		PR_REMOVE_AND_INIT_LINK(head);
		tpool->timerq.cnt--;
		jobp = JOB_LINKS_PTR(head);
		delete_job(jobp);
	}

	PR_ASSERT(0 == tpool->jobq.cnt);
	PR_ASSERT(0 == tpool->ioq.cnt);
	PR_ASSERT(0 == tpool->timerq.cnt);

	delete_threadpool(tpool);
	return rval;
}
Пример #17
0
job_t* readcmdline(char *msg) 
{

	fprintf(stdout, "%s", msg);

	char *cmdline = (char *)calloc(MAX_LEN_CMDLINE, sizeof(char));
	if(!cmdline) {
	    	fprintf(stderr, "%s\n","malloc: no space");
        	return NULL;
    	}
	fgets(cmdline, MAX_LEN_CMDLINE, stdin);

	/* sequence is true only when the command line contains ; */
	bool sequence = false;
	/* seq_pos is used for storing the command line before ; */
	int seq_pos = 0;

	int cmdline_pos = 0; /*iterator for command line; */

    	job_t *first_job = NULL;

	while(1) {
		job_t *current_job = find_last_job(first_job);

		int cmd_pos = 0;        /* iterator for a command */
		int iofile_seek = 0;    /*iofile_seek for file */
		bool valid_input = true; /* check for valid input */
		bool end_of_input = false; /* check for end of input */

		/* cmdline is NOOP, i.e., just return with spaces */
		while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */
		if(cmdline[cmdline_pos] == '\n' || cmdline[cmdline_pos] == '\0' || feof(stdin))
			return NULL;

		/* Check for invalid special symbols (characters) */
		if(cmdline[cmdline_pos] == ';' || cmdline[cmdline_pos] == '&' 
			|| cmdline[cmdline_pos] == '<' || cmdline[cmdline_pos] == '>' || cmdline[cmdline_pos] == '|')
			return NULL;

		char *cmd = (char *)calloc(MAX_LEN_CMDLINE, sizeof(char));
		if(!cmd) {
	        	fprintf(stderr, "%s\n","malloc: no space");
            		return NULL;
        	}

		job_t *newjob = (job_t *)malloc(sizeof(job_t));
		if(!newjob) {
	       		fprintf(stderr, "%s\n","malloc: no space");
            		return NULL;
        	}

		if(!first_job)
			first_job = current_job = newjob;
		else {
			current_job->next = newjob;
			current_job = current_job->next;
		}

		if(!init_job(current_job)) {
	        	fprintf(stderr, "%s\n","malloc: no space");
			delete_job(current_job,first_job);
            		return NULL;
        	}

        	process_t *newprocess = (process_t *)malloc(sizeof(process_t));
		if(!newprocess) {
	        	fprintf(stderr, "%s\n","malloc: no space");
			delete_job(current_job,first_job);
            		return NULL;
        	}
		if(!init_process(newprocess)){
	        	fprintf(stderr, "%s\n","malloc: no space");
			delete_job(current_job,first_job);
            		return NULL;
        	}

		process_t *current_process = NULL;

		if(!current_job->first_process)
			current_process = current_job->first_process = newprocess;
		else {
			current_process->next = newprocess;
			current_process = current_process->next;
		}

		while(cmdline[cmdline_pos] != '\n' && cmdline[cmdline_pos] != '\0') {

			switch (cmdline[cmdline_pos]) {

			    case '<': /* input redirection */
				current_process->ifile = (char *) calloc(MAX_LEN_FILENAME, sizeof(char));
				if(!current_process->ifile) {
					fprintf(stderr, "%s\n","malloc: no space");
					delete_job(current_job,first_job);
					return NULL;
                		}
				++cmdline_pos;
				while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */
				iofile_seek = 0;
				while(cmdline[cmdline_pos] != '\0' && !isspace(cmdline[cmdline_pos])){
					if(MAX_LEN_FILENAME == iofile_seek) {
	                    			fprintf(stderr, "%s\n","malloc: no space");
			            		delete_job(current_job,first_job);
                        			return NULL;
                    			}
					current_process->ifile[iofile_seek++] = cmdline[cmdline_pos++];
				}	
				
				current_process->ifile[iofile_seek] = '\0';
				current_job->mystdin = INPUT_FD;
				while(isspace(cmdline[cmdline_pos])) {
					if(cmdline[cmdline_pos] == '\n')
						break;
					++cmdline_pos;
				}
				valid_input = false;
				break;
			
			    case '>': /* output redirection */
				current_process->ofile = (char *) calloc(MAX_LEN_FILENAME, sizeof(char));
				if(!current_process->ofile) {
	                		fprintf(stderr, "%s\n","malloc: no space");
			        	delete_job(current_job,first_job);
                    			return NULL;
                		}
				++cmdline_pos;
				while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */
				iofile_seek = 0;
				while(cmdline[cmdline_pos] != '\0' && !isspace(cmdline[cmdline_pos])){
					if(MAX_LEN_FILENAME == iofile_seek) {
	                    			fprintf(stderr, "%s\n","malloc: no space");
			            		delete_job(current_job,first_job);
                        			return NULL;
                    			}
					current_process->ofile[iofile_seek++] = cmdline[cmdline_pos++];
				}
				
				current_process->ofile[iofile_seek] = '\0';
				current_job->mystdout = OUTPUT_FD;
				while(isspace(cmdline[cmdline_pos])) {
					if(cmdline[cmdline_pos] == '\n')
						break;
					++cmdline_pos;
				}
				
				
				valid_input = false;
				break;

			   case '|': /* pipeline */
				cmd[cmd_pos] = '\0';
				process_t *newprocess = (process_t *)malloc(sizeof(process_t));
				if(!newprocess) {
	                		fprintf(stderr, "%s\n","malloc: no space");
			        	delete_job(current_job,first_job);
                    			return NULL;
                		}
				if(!init_process(newprocess)) {
					fprintf(stderr, "%s\n","init_process: failed");
					delete_job(current_job,first_job);
				    	return NULL;
                		}
				if(!readprocessinfo(current_process, cmd)) {
					fprintf(stderr, "%s\n","parse cmd: error");
					delete_job(current_job,first_job);
			    		return NULL;
				}
				current_process->next = newprocess;
				current_process = current_process->next;
				++cmdline_pos;
				cmd_pos = 0; /*Reinitialze for new cmd */
				valid_input = true;	
				break;

			   case '&': /* background job */
				current_job->bg = true;
				while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */
				if(cmdline[cmdline_pos+1] != '\n' && cmdline[cmdline_pos+1] != '\0')
					fprintf(stderr, "reading bg: extra input ignored");
				end_of_input = true;
				break;

			   case ';': /* sequence of jobs*/
				sequence = true;
				strncpy(current_job->commandinfo,cmdline+seq_pos,cmdline_pos-seq_pos);
				seq_pos = cmdline_pos + 1;
				break;	

			   case '#': /* comment */
				end_of_input = true;
				break;

			   default:
				if(!valid_input) {
					fprintf(stderr, "%s\n", "reading cmdline: could not fathom input");
			        	delete_job(current_job,first_job);
                    			return NULL;
                		}
				if(cmd_pos == MAX_LEN_CMDLINE-1) {
					fprintf(stderr,"%s\n","reading cmdline: length exceeds the max limit");
			        	delete_job(current_job,first_job);
                    			return NULL;
                		}
				cmd[cmd_pos++] = cmdline[cmdline_pos++];
				break;
			}
			if(end_of_input || sequence)
				break;
		}
		cmd[cmd_pos] = '\0';
		
		if(!readprocessinfo(current_process, cmd)) {
			fprintf(stderr,"%s\n","read process info: error");
			delete_job(current_job,first_job);
            		return NULL;
        	}
		if(!sequence) {
			strncpy(current_job->commandinfo,cmdline+seq_pos,cmdline_pos-seq_pos);
			break;
		}
		sequence = false;
		++cmdline_pos;
	}
	return first_job;
}
Пример #18
0
/* 
 * builtin_cmd - If the user has typed a built-in command then execute
 * it immediately.  
 */
bool builtin_cmd(job_t *last_job, int argc, char **argv) 
{

	    /* check whether the cmd is a built in command
        */

  if (!strcmp("quit", argv[0])) {
    /* Your code here */
    exit(EXIT_SUCCESS);
  }
  else if (!strcmp("jobs", argv[0])) {
    /* Your code here */
    job_t* currentJob = active_jobs_head;
    job_t* deletedJob = NULL;

    while(currentJob != NULL) {
      // print active jobs and then change notified to 0

      //if((currentJob->first_process)->completed == true && currentJob->notified == false) {

      //need to check if every process has completed for a job to be complete, not just the first process
      if (job_is_completed(currentJob) == true)
      {
        printf("%d (Completed): %s\n", currentJob->pgid, currentJob->commandinfo);
        deletedJob = currentJob;

         //currentJob->notified = true;
      }
      //otherwise it is stopped
      else if (job_is_stopped(currentJob) == true)
      {
        printf("%d (Stopped): %s\n", currentJob->pgid, currentJob->commandinfo);
      }

      else
      {
        printf("%d (Running): %s\n", currentJob->pgid, currentJob->commandinfo);
      }

      currentJob = currentJob->next;

      // delete job after it is completed, don't need to save notified 
     
      if (deletedJob != NULL) 
      {
        if (deletedJob == active_jobs_head)
        {
          active_jobs_head = deletedJob->next;
          free_job(deletedJob); //TBD warning about this?
        }
        else
        {
          delete_job(deletedJob, active_jobs_head);
        }
        deletedJob = NULL;
      }
    }
    return true;
  }

  else if (!strcmp("cd", argv[0])) {
    int chdir_return = chdir(argv[1]);
    if(chdir_return == -1) {
      printf("cd: %s: No such file or directory\n", argv[1]);
    }
    return true;
  }
  else if (!strcmp("bg", argv[0])) {
    /* Your code here */
    job_t* currentJob = active_jobs_head;
    process_t* p2;

    if(argv[1] == NULL) 
    {
      // continue most recent stopped job

      //use find_last_job
      currentJob = find_last_job(active_jobs_head);

      continue_job(currentJob);
      seize_tty(currentJob->pgid);


      p2 = currentJob->first_process;

      while(p2 != NULL)
      {
        p2->stopped = false;
        
        struct sigaction action;
        action.sa_sigaction = sighandler;

        sigfillset(&action.sa_mask);
        action.sa_flags = SA_SIGINFO;
        sigaction(SIGCHLD, &action, NULL);

        p2 = p2->next;
      }
      seize_tty(getpid());
    }

    else 
    {
      pid_t job_number = atoi(argv[1]);

      
      while(currentJob != NULL) {
        // Need to eventually iterate through all processes?
        
        if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) {
          //seize_tty(currentJob->pgid);
          continue_job(currentJob); 
          seize_tty(currentJob->pgid);

          p2 = currentJob->first_process;
          while (p2 != NULL)
          {
            p2->stopped = false; 

            struct sigaction action;
            action.sa_sigaction = sighandler;

            sigfillset(&action.sa_mask);
            action.sa_flags = SA_SIGINFO;
            sigaction(SIGCHLD, &action, NULL);
            p2 = p2->next;
          }

          seize_tty(getpid());
          break;
        }
        else if (currentJob->pgid == job_number) {
          printf("%s\n", "This process wasn't stopped`");
        }
        else {
          printf("%s\n", "This job number is not the requested one");
        }
        currentJob = currentJob->next;
      }
    }
    return true;
  }


  else if (!strcmp("fg", argv[0])) {
    /* Your code here */
    job_t* currentJob = active_jobs_head;
    process_t* p2;

    if(argv[1] == NULL) {
      // continue most recent stopped job

      //use find_last_job
      currentJob = find_last_job(active_jobs_head);
      continue_job(currentJob);
      seize_tty(currentJob->pgid);


      p2 = currentJob->first_process;

      while(p2 != NULL)
      {
        waiting(p2);
        p2 = p2->next;
      }
      seize_tty(getpid());
    }
    else {
      pid_t job_number = atoi(argv[1]);

      
      while(currentJob != NULL) {
        
        
        if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) {
          //seize_tty(currentJob->pgid);
          continue_job(currentJob); 
          seize_tty(currentJob->pgid);

          p2 = currentJob->first_process;
          while (p2 != NULL)
          {
            waiting(p2);
            p2 = p2->next;
          }
          seize_tty(getpid());
          break;
        }
        else if (currentJob->pgid == job_number) {
          printf("%s\n", "This process wasn't stopped`");
        }
        else {
          printf("%s\n", "This job number is not the requested one");
        }
        currentJob = currentJob->next;
      }
    }
    return true;
  }
  /* not a builtin command */
  return false;
}