/*
 * Handler for command with PIO data-in phase (Read/Read Multiple).
 */
static ide_startstop_t task_in_intr(ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
	struct request *rq = hwif->rq;
	u8 stat = hwif->tp_ops->read_status(hwif);

	/* Error? */
	if (stat & ATA_ERR)
		return task_error(drive, rq, __func__, stat);

	/* Didn't want any data? Odd. */
	if ((stat & ATA_DRQ) == 0)
		return task_in_unexpected(drive, rq, stat);

	ide_pio_datablock(drive, rq, 0);

	/* Are we done? Check status and finish transfer. */
	if (!hwif->nleft) {
		stat = wait_drive_not_busy(drive);
		if (!OK_STAT(stat, 0, BAD_STAT))
			return task_error(drive, rq, __func__, stat);
		task_end_request(drive, rq, stat);
		return ide_stopped;
	}

	/* Still data left to transfer. */
	ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);

	return ide_started;
}
Example #2
0
/* insert new object at head of queue (after queue->q_ptr) */
int
qhead::putback(object* p)
{
	oqueue* q = qh_queue;

	if (p->o_next) task_error(E_BACKOBJ, this);
ll:
	if (q->q_count++ < q->q_max) {
		if (q->q_count == 1) {
			q->q_ptr = p;
			p->o_next = p;
		}
		else {
			object* oo = q->q_ptr;
			p->o_next = oo->o_next;
			oo->o_next = p;
		}
		return 1;
	}

	switch (qh_mode) {
	case WMODE:
	case EMODE:
		task_error(E_BACKFULL, this);
		goto ll;
	case ZMODE:
		return 0;
	}
}
Example #3
0
void sched.schedule()
/* schedule either clock_task or front of run_chain */
{
DB(("%x->sched::schedule( )\n",this));
	register sched* p;
	register long tt;

lll:
	DB(("	run_chain:  x%x\n", run_chain));
	if (p = run_chain) {
		run_chain = (sched*) p->o_next;
		p->o_next = 0;
	}
	else {
		if (exit_fct) (*exit_fct)();
		exit(0);
	}

	tt = p->s_time;
	DB(("	thistask->s_time, p->s_time, clock == %ld, %ld, %ld\n", thistask->s_time, tt, clock));
	if (tt != clock) {
		if (tt < clock) task_error(E_SCHTIME,this);
		clock = tt;
		if (clock_task) {
			if (clock_task->s_state != IDLE)
				task_error(E_CLOCKIDLE,this);
			/* clock_task preferred */
			p->o_next = (object*) run_chain;
			run_chain = p;
			p = (sched*) clock_task;
		}
	}

	switch (p->o_type) {
	case TIMER: /* time is up; "delete" timer & schedule next task */
		p->s_state = TERMINATED;
		p->alert();
		goto lll;
	case TASK:
		if (p != this) {
			if (thistask && thistask->s_state != TERMINATED)
				thistask->save();
			thistask = (task*) p;
			thistask->restore();
		}
		break;
	default:
		DB(("object(%x) type == %x\n", p, p->o_type));
		task_error(E_SCHOBJ,this);
	}
} /* schedule */
Example #4
0
void sched.insert(int d, object* who)
/*
	schedule THIS to run in ``d'' time units
	inserted by who
*/
{
	register sched * p;
	register sched * pp;
	register long tt = s_time = clock + d;

DB(("%x->sched::insert( %x, %x )\n",this,d,who));
	switch (s_state) {
	case TERMINATED:
		task_error(E_RESTERM,this);
		break;
	case IDLE:
		break;
	case RUNNING:
		if (this != (class sched *)thistask) task_error(E_RESRUN,this);
	}

	if (d<0) task_error(E_NEGTIME,this);	

	if (o_next) task_error(E_RESOBJ,this);

	s_state = RUNNING;
	if (o_type == TASK) ((task *) this)->t_alert = who;

	/* run_chain ordered by s_time */
	if (p = run_chain) {
		if (tt < p->s_time) {
			o_next = (object*) run_chain;
			run_chain = this;
		}
		else {
			while (pp = (sched *) p->o_next) {
				if (tt < pp->s_time) {
					o_next = pp;
					p->o_next = this;
					return;
				}
				else p = pp;
			}
			p->o_next = this;
		}
	}
	else 
		run_chain = this;
}
Example #5
0
// q->q_ptr points to last object.  last->o_next points to first object.
// first->o_next points to the next object.
object*
qhead::get()
{
	register oqueue* q = qh_queue;
ll:
	if (q->q_count) {
		register object* oo = q->q_ptr;
		register object* p = oo->o_next;
		oo->o_next = p->o_next;
		p->o_next = 0;
		if (q->q_count-- == q->q_max) {
			qtail* t = q->q_tail;
			if (t) t->alert();
		};
		return p;
	}

	switch (qh_mode) {
	case WMODE:
		this_task()->sleep(this);
		goto ll;
	case EMODE:
		task_error(E_GETEMPTY, this);
		goto ll;
	case ZMODE:
		return 0;
	}
}
Example #6
0
void start_threads(void) {
  if (running) task_error("threads already running");
  if (pthread_barrier_init(&barrier, NULL, threads)) {
    task_error("Can't create a barrier");
  }
  running = TRUE;
  for (unsigned int id = 0; id<threads; id++) task_args[id].id = id;
  pthread_attr_t attributes;
  pthread_attr_init(&attributes);
  pthread_attr_setstacksize(&attributes, 10*1024*1024); /* hardwired 10MB */
  for (unsigned int id = 0; id<threads; id++) {
    if (pthread_create(&thread[id], &attributes, task[id],
		       (void *)&task_args[id])) {
      task_error("Can't start thread %u", id);
    }
  }
  pthread_attr_destroy(&attributes);
}
/*
 * Handler for command with PIO data-out phase (Write/Write Multiple).
 */
static ide_startstop_t task_out_intr (ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
	struct request *rq = hwif->rq;
	u8 stat = hwif->tp_ops->read_status(hwif);

	if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
		return task_error(drive, rq, __func__, stat);

	/* Deal with unexpected ATA data phase. */
	if (((stat & ATA_DRQ) == 0) ^ !hwif->nleft)
		return task_error(drive, rq, __func__, stat);

	if (!hwif->nleft) {
		task_end_request(drive, rq, stat);
		return ide_stopped;
	}

	/* Still data left to transfer. */
	ide_pio_datablock(drive, rq, 1);
	ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);

	return ide_started;
}
Example #8
0
void stop_threads(void) {
  /* needs work: Technically, can't access running here without a mutex. */
  if (running&&!halt) {
    pthread_mutex_lock(&halt_mutex);
    halt = TRUE;
    pthread_mutex_unlock(&halt_mutex);
    for (unsigned int id = 0; id<threads; id++) {
      if (pthread_join(thread[id], NULL)!=0) {
	task_error("Can't join thread %u", id);
      }
    }
    pthread_barrier_destroy(&barrier);
    halt = FALSE;
  }
}
Example #9
0
int sched.result()
/* wait for termination and retrieve result */
{
DB(("%x->sched::result( )\n", this));
DB(("     o_type == x%x\n", o_type));
	if (this == (sched*)thistask) task_error(E_RESULT,0);
	while (s_state != TERMINATED) {
		remember(thistask);
		DB(("     o_type == x%x -- remember(x%x)\n", o_type,thistask));
		thistask->sleep();
		DB(("     o_type == x%x -- x%x->sleep()\n", o_type,thistask));
		forget(thistask);
		DB(("     o_type == x%x -- forget(x%x)\n", o_type,thistask));
	}

	return (int) s_time;
}
Example #10
0
int 
task_abandon (struct task_act *tk)
{
	struct oper_act	* on;

	DLOG(log_dsap, LLOG_TRACE, ("task_abandon"));

	for(on = tk->tk_operlist; on != NULLOPER; on = on->on_next_task) {
		on->on_state = ON_ABANDONED;
		on->on_task = NULLTASK;
		if (on->on_dsas) {
			di_desist (on->on_dsas);
			on -> on_dsas = NULL_DI_BLOCK;
		}
	}

	ds_error_free (&tk->tk_resp.di_error.de_err);
	tk->tk_resp.di_error.de_err.dse_type = DSE_ABANDONED;
	task_error(tk);

	return(OK);
}
Example #11
0
double current_time(void) {
  struct timeval time;
  if (gettimeofday(&time, NULL)!=0) task_error("gettimeofday failed");
  /* needs work: Will it convert division into multiplication? */
  return ((double)time.tv_sec)+((double)time.tv_usec)/1e6;
}
Example #12
0
void *task_malloc(size_t size) {
  void *p = malloc(size);
  if (p==NULL) task_error("Out of memory");
  return p;
}
Example #13
0
int 
conn_extract (struct connection *conn)
{
	/*
	* Extract all the operations made on this connection, and all
	* the tasks (and their derivative operations) made on the connection;
	* then remove the connection from the list of active connections.
	*/

	struct oper_act     * on;
	struct oper_act     * on_next;
	struct task_act     * tk;
	struct task_act     * tk_next;
	struct connection	* cn;
	struct connection	**cn_p;
	struct DSError	* err;

	DLOG (log_dsap,LLOG_TRACE, ("conn_extract"));

#ifdef QUIPU_CONSOLE
	/* SPT: Catch this close and indicate it on the open_calls */
	closing_analyse(conn) ;
#endif /* QUIPU_CONSOLE */

	if(conn == NULLCONN) {
		LLOG(log_dsap, LLOG_EXCEPTIONS, ("Extracting NULLCONN!!!"));
		return;
	}

	cn_p = &(connlist);
	for(cn=connlist; cn!=NULLCONN; cn=cn->cn_next) {
		DLOG(log_dsap, LLOG_DEBUG, ("checking connlist"));
		if(cn == conn)
			break;

		cn_p = &(cn->cn_next);
	}
	if(cn==NULLCONN) {
		LLOG(log_dsap, LLOG_EXCEPTIONS, ("conn_extract - connection not in connlist"));
		return;
	} else {
		/* Cut connection loose from global list */
		DLOG(log_dsap, LLOG_DEBUG, ("Extracting conn from connlist"));
		(*cn_p) = cn->cn_next;
		conns_used--;
	}

	for(on=conn->cn_operlist; on!=NULLOPER; on=on_next) {
		on_next = on->on_next_conn;
		oper_fail_wakeup (on);
	}

	for(tk=conn->cn_tasklist; tk!=NULLTASK; tk=tk_next) {
		tk_next = tk->tk_next;
		err = &(tk->tk_resp.di_error.de_err);
		if((err->dse_type != DSE_REFERRAL) && (err->dse_type != DSE_DSAREFERRAL)) {
			err->dse_type = DSE_SERVICEERROR;
			err->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE;
		}
		task_error(tk);
		task_extract(tk);
	}

	conn_free(conn);
}
Example #14
0
void setclock(long t)
{
	if (clock) task_error(E_SETCLOCK,0);
	clock = t;
}
Example #15
0
int 
timeout_task (struct task_act *tk)
{
	struct oper_act	* on;
	struct DSError	* err = &(tk->tk_resp.di_error.de_err);
	struct ds_search_task *tmp;

	DLOG(log_dsap, LLOG_TRACE, ("timeout_task"));
	for(on=tk->tk_operlist; on!=NULLOPER; on=on->on_next_task) {
		/* Time out operations started by task */
		on->on_state = ON_ABANDONED;
		on->on_task = NULLTASK;
		if (on->on_dsas) {
			di_desist (on->on_dsas);
			on -> on_dsas = NULL_DI_BLOCK;
		}

	}

	if(tk->tk_dx.dx_arg.dca_dsarg.arg_type != OP_SEARCH) {
		ds_error_free (err);
		err->dse_type = DSE_SERVICEERROR;
		if (tk->tk_timed == TRUE)
			err->ERR_SERVICE.DSE_sv_problem = DSE_SV_TIMELIMITEXCEEDED;
		else /* tk->tk_timed == 2 */
			err->ERR_SERVICE.DSE_sv_problem = DSE_SV_ADMINLIMITEXCEEDED;
		task_error(tk);
		task_extract(tk);
	} else {
		/* Do search collation */
		if ((tk->tk_state == TK_ACTIVE) && (tk->local_st == NULL_ST)) {
			ds_error_free (err);
			/* nothing happened yet... */
			err->dse_type = DSE_SERVICEERROR;
			if (tk->tk_timed == TRUE)
				err->ERR_SERVICE.DSE_sv_problem = DSE_SV_TIMELIMITEXCEEDED;
			else /* tk->tk_timed == 2 */
				err->ERR_SERVICE.DSE_sv_problem = DSE_SV_ADMINLIMITEXCEEDED;
			task_error(tk);
		} else {
			/* send the results we have got... */
			tk->tk_result = &(tk->tk_resp.di_result.dr_res);
			tk->tk_result->dcr_dsres.result_type = tk->tk_dx.dx_arg.dca_dsarg.arg_type;
			tk->tk_resp.di_type = DI_RESULT;
			if (tk->tk_timed == TRUE)
				tk->tk_resp.di_result.dr_res.dcr_dsres.res_sr.CSR_limitproblem = LSR_TIMELIMITEXCEEDED;
			else /* tk->tk_timed == 2 */
				tk->tk_resp.di_result.dr_res.dcr_dsres.res_sr.CSR_limitproblem = LSR_ADMINSIZEEXCEEDED;

			/* Go through sub-tasks and add a POQ for each */
			for(tmp=tk->referred_st; tmp!= NULL_ST; tmp=tmp->st_next)
				add_cref2poq (&tk->tk_result->dcr_dsres.res_sr,tmp->st_cr);

			task_result(tk);

			st_free_dis(&tk->referred_st,1);
		}

		task_extract(tk);
	}

}