Ejemplo n.º 1
0
Archivo: tm.c Proyecto: jschiefer/bibo
/*! \param tid must be valid process ID, or undefined behaviour will result!
*/
void kill(tid_t tid) {
    grab_kernel_lock(); 
    switch (tid->tflags & T_STATE) {
	case T_WAITING:
	    /* Mark as zombie.  
	     * It will be killed by the wait method after releasing lock.
	     */
	    make_running(tid);
	    tid->tflags = (tid->tflags & ~T_STATE) | T_ZOMBIE;
	    break;

	case T_RUNNING:
	    if (tid == ctid) {
		/* delay killing until this thread frees the kernel lock */
		victim = tid;
		enqueue_handler(&killer_handler);
	    } else {
		reap_to_death(tid);
	    }
	    break;

	default:
	    /* thread was already killed */
	    break;
    }
    release_kernel_lock();    
}
Ejemplo n.º 2
0
Archivo: tm.c Proyecto: jschiefer/bibo
/*! \param flags T_USER to shutdown user tasks, T_USER | T_KERNEL for all tasks
 */
void shutdown_tasks(tflags_t flags) {
    tdata_t *td, *nexttd;
    
    grab_kernel_lock();
    DEBUG("sd:%d",flags);
    
    /* Iterate running queue */
    td = td_idle.next;
    while (td != &td_idle) {
	DEBUG("tdr:%04x",td);
	if ((td->tflags & ~flags & T_KERNEL) == 0) {
	    td->tflags |= T_SHUTDOWN;
	}
	td = td->next;
    }

    /* Now iterate waiting queue (this adds them to running queue) */
    td = waiters.next;
    while (td != &waiters) {
	DEBUG("tdw:%04x",td);
	nexttd = td->next;
	if ((td->tflags & ~flags & T_KERNEL) == 0) {
	    make_running(td);
	    td->tflags |= T_SHUTDOWN;
	}
	td = nexttd;
    }
    
    release_kernel_lock();
}
Ejemplo n.º 3
0
Archivo: tm.c Proyecto: jschiefer/bibo
/*! \param msec sleep duration in milliseconds
    \return number of milliseconds left if interrupted, else 0.
 */
unsigned int msleep(unsigned int msec)
{
    grab_kernel_lock();
    wait_timeout(msec);
    release_kernel_lock();
    return 0;
}
Ejemplo n.º 4
0
int pthread_mutex_trylock(pthread_mutex_t * mutex) {
    waitqueue_t entry;
    tid_t owner;
    grab_kernel_lock();
    if (mutex->owner != NULL)
	return EBUSY;
    mutex->owner = ctid;
    release_kernel_lock();
    return 0;
}
Ejemplo n.º 5
0
/*
 * schedule() is the main scheduler function.
 */
asmlinkage void __sched schedule(void)
{
        struct task_struct *prev, *next;
        unsigned long *switch_count;
        struct rq *rq;
        int cpu;

need_resched:
        preempt_disable();
        cpu = smp_processor_id();
        rq = cpu_rq(cpu);
        rcu_sched_qs(cpu);
        prev = rq->curr;
        switch_count = &prev->nivcsw;

        release_kernel_lock(prev);
need_resched_nonpreemptible:

        schedule_debug(prev);

        if (sched_feat(HRTICK))
                hrtick_clear(rq);

        raw_spin_lock_irq(&rq->lock);
        update_rq_clock(rq);
        clear_tsk_need_resched(prev);

	        if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
                if (unlikely(signal_pending_state(prev->state, prev)))
                        prev->state = TASK_RUNNING;
                else
                        deactivate_task(rq, prev, 1);
                switch_count = &prev->nvcsw;
        }

        pre_schedule(rq, prev);

        if (unlikely(!rq->nr_running))
                idle_balance(cpu, rq);

        put_prev_task(rq, prev);
        next = pick_next_task(rq);

        if (likely(prev != next)) {
                sched_info_switch(prev, next);
                perf_event_task_sched_out(prev, next);

                rq->nr_switches++;
                rq->curr = next;
                ++*switch_count;

                context_switch(rq, prev, next); /* unlocks the rq */
Ejemplo n.º 6
0
Archivo: mm.c Proyecto: jschiefer/bibo
//! return the number of bytes of unallocated memory
int mm_free_mem(void) {
    int free = 0;
    meminfo_t *ptr;

    grab_kernel_lock();

    // Iterate through the free list
    for (ptr = mm_first_free; ptr; ptr = ptr->nextfree)
        free += (size_t)ptr->next - (size_t)ptr - 4;

    release_kernel_lock();
    return free;
}
Ejemplo n.º 7
0
Archivo: mm.c Proyecto: jschiefer/bibo
/*! \param size requested block size
    \return 0 on error, else pointer to block.
*/
void *malloc(size_t size) {
    meminfo_t *ptr;
    meminfo_t **pptr;

    size = (size+1) & ~1;       // only multiples of 2
    if (size < 4)
        size = 4;

    grab_kernel_lock();
    pptr = &mm_first_free;

    while((ptr = *pptr)) {
        int blocksize = ((void*)ptr->next - (void*)ptr);
        /* big enough? */
        if (blocksize >= size + MM_HEADER_SIZE) {
            /* set flags */
            ptr->flags = (ctid->tflags & T_KERNEL) ? MM_KERNEL : MM_USER;

            /* split this block? */
            if(blocksize >= size + MM_SPLIT_THRESH) {
                meminfo_t *next = (meminfo_t*) ((size_t)ptr + (size + 4));
                next->flags = MM_FREE;
                next->next = ptr->next;
                ptr->next->prev = next;
                next->nextfree = ptr->nextfree;
                ptr->next = next;
                *pptr = next;
            } else {
                ptr->next->next = (void*) ((size_t) ptr->next->next & ~1);
                *pptr = ptr->nextfree;
            }
            release_kernel_lock();
            return (void*) &(ptr->nextfree);
        }
        pptr = &ptr->nextfree;
    }
    release_kernel_lock();
    return NULL;
}
Ejemplo n.º 8
0
Archivo: tm.c Proyecto: jschiefer/bibo
/*! (does not speed up the system clock)
*/
void yield(void) {
    grab_kernel_lock();
    if (ctid->next->priority == ctid->priority) {
	tid_t td = ctid->next;
	td->prev = ctid->prev;
	ctid->prev->next = td;
	while (td->priority == ctid->priority)
	    td = td->next;

	ctid->next = td;
	ctid->prev = td->prev;
	td->prev->next = ctid;
	td->prev = ctid;
	/* trigger scheduler */
	kernel_lock &= ~0x80;
    }
    release_kernel_lock();
}
Ejemplo n.º 9
0
Archivo: mm.c Proyecto: jschiefer/bibo
/*! \param the_ptr pointer to block
*/
void free(void *the_ptr) {
    meminfo_t *ptr = (meminfo_t*) ((size_t)the_ptr - 6);
    if (the_ptr==NULL)
        return;

    grab_kernel_lock();
    if (((size_t)ptr->next & 1)) {
        /* merge with previous free block */
        meminfo_t *next = (meminfo_t*) ((size_t) ptr->next & ~1);
        if (next->flags == MM_FREE) {
            /* merge with next free block and dequeue that */
            ptr->prev->next = next->next;
            next->next->prev = ptr->prev;
            ptr->prev->nextfree = next->nextfree;
        } else {
            /* tell next block that previous block is now free */
            next->next = (void*) ((size_t) next->next | 1);
            ptr->prev->next = next;
            next->prev = ptr->prev;
        }
    } else {
        /* enqueue block to free list */
        ptr->flags = MM_FREE;
        meminfo_t **prev = &mm_first_free;
        while (*prev && *prev < ptr)
            prev = &((*prev)->nextfree);
        if (ptr->next->flags == MM_FREE) {
            /* merge with next free block */
            ptr->nextfree = ptr->next->nextfree;
            ptr->next = ptr->next->next;
        } else {
            /* New free block */
            ptr->next->next = (void*) ((size_t) ptr->next->next | 1);
            ptr->nextfree = *prev;
        }
        ptr->next->prev = ptr;
        *prev = ptr;
    }
    release_kernel_lock();
}
Ejemplo n.º 10
0
int pthread_mutex_lock(pthread_mutex_t * mutex) {
    waitqueue_t entry;
    tid_t owner;
    tflags_t flags = 0;
    // check if mutex is available, if not, go to sleep
    grab_kernel_lock();
    if ((owner = mutex->owner) != NULL) {
	if (owner->priority < ctid->priority) {
	    /* propagate priority to prevent priority inversion */
	    owner->priority = ctid->priority;
	    if (!(owner->tflags & T_IDLE)
		&& ctid->next != owner) {
		/* resort run queue */
		owner->prev->next = mutex->next;
		owner->next->prev = mutex->prev;
		owner->next = ctid->next;
		owner->prev = ctid->prev;
		ctid->next->prev = owner;
		ctid->next = owner;
	    }
	}
	entry.thread = ctid;
	add_to_waitqueue(&mutex->waiters, &entry);
	do {
	    wait();
	    if (shutdown_requested()) {
		/* temporarily clear shutdown but remember it for later */
		ctid->flags &= ~T_SHUTDOWN;
		shutdown = T_SHUTDOWN;
	    }
	} while (mutex->owner != NULL);
	remove_from_waitqueue(&entry);
    }
    mutex->priority = ctid->priority;
    mutex->owner = ctid;
    ctid->flags |= shutdown;
    release_kernel_lock();
    return 0;
}
Ejemplo n.º 11
0
int pthread_mutex_unlock(pthread_mutex_t * sem) {
    grab_kernel_lock();
    /* restore priority */
    ctid->priority = mutex->priority;
    if (ctid->next->priority > ctid->priority) {
	tid_t td;
	/* resort run queue */
	ctid->prev->next = ctid->next;
	ctid->next->prev = ctid->prev;
	td = ctid->next;
	do {
	    td = td->next;
	} while (td->priority > ctid->priority);
	ctid->next = td;
	ctid->prev = td->prev;
	td->prev->next = ctid;
	td->prev = ctid;
    }
    mutex->owner = NULL;
    if (mutex->waiters)
	wakeup_single(mutex->waiters);
    release_kernel_lock();
    return 0;
}
Ejemplo n.º 12
0
Archivo: tm.c Proyecto: jschiefer/bibo
/*! \param flags T_USER to shutdown user tasks, T_USER | T_KERNEL for all tasks
*/
void killall(tflags_t flags) {
    tdata_t *td, *nexttd;
    
    grab_kernel_lock();
    
    /* Now iterate running queue */
    td = td_idle.next;
    while (td != &td_idle) {
	nexttd = td->next;
	if ((td->tflags & ~flags & T_KERNEL) == 0) {
	    if (td != ctid) {
		reap_to_death(td);
	    } else {
		victim = td;
		enqueue_handler(&killer_handler);
	    }
	}
	td = nexttd;
    }

    /* iterate waiting queue */
    td = waiters.next;
    while (td != &waiters) {
	nexttd = td->next;
	if ((td->tflags & ~flags & T_KERNEL) == 0) {
	  make_running(td);
	  /* Mark as zombie.  
	   * It will be killed by the wait method after releasing lock.
	   */
	  td->tflags = (td->tflags & ~T_STATE) | T_ZOMBIE;
	}
	td = nexttd;
    }

    release_kernel_lock();
}
Ejemplo n.º 13
0
asmlinkage void sch$sched(int from_sch$resched) {
  int cpuid = smp_processor_id();
  struct _cpu * cpu=smp$gl_cpu_data[cpuid]; 
  struct _pcb *next = 0, *curpcb;
  int curpri, affinity;
  unsigned char tmppri;
  unsigned long qhead = 0;
  int after, before;

  curpcb=cpu->cpu$l_curpcb;
  curpri=cpu->cpu$b_cur_pri;

  //  if (!countme--) { countme=500; printk("."); }

  if (from_sch$resched == 1)
    goto skip_lock;

#if 0

  // NOT YET??? nope,not an interrupt. pushpsl+setipl/vmslock instead?

  if (intr_blocked(IPL$_SCHED))
    return;

  regtrap(REG_INTR,IPL$_SCHED);
#endif

  int ipl = getipl();
  if (ipl != 8 || SPIN_SCHED.spl$l_spinlock == 0)
    panic("schsch\n");

#if 0
  // temp workaround
  // must avoid nesting, since I do not know how to get out of it
  setipl(IPL$_SCHED);
  vmslock(&SPIN_SCHED,-1);
#endif

  /** clear cpu_priority for current pri bit - TODO: where did this come from? */

  sch$al_cpu_priority[curpri]=sch$al_cpu_priority[curpri] & (~ cpu->cpu$l_cpuid_mask );

  /** skip if ... TODO: from where? */

  if (sch$al_cpu_priority[curpri]) 
    goto skip_lock;

  /** clear active_priority for current pri bit - TODO: where did this come from? */

  sch$gl_active_priority=sch$gl_active_priority & (~ (1 << (31-curpri)));

  //if (spl(IPL$_SCHED)) return;
  //  old=spl(IPL$_SCHED);

  /** now 4 linux leftovers */

  spin_lock_prefetch(&runqueue_lock);

  if (!curpcb->active_mm) BUG();

  release_kernel_lock(curpcb, cpuid);

  spin_lock_irq(&runqueue_lock);

 skip_lock:

  /** reset cpu affinity TODO: from where? */

  affinity=0;
  struct _pcb * aff_next = 0;

  /** find highest pri comqueue */

  tmppri=ffs(sch$gl_comqs);
#ifdef DEBUG_SCHED
  if (mydebug5)
    printk("ffs %x %x\n",tmppri,sch$gl_comqs);
#endif

  if (!tmppri) {
    /** if none found, idle */
#if 0
    // spot for more vms sched
    goto sch$idle;
#endif
  go_idle:
    /** set bit in idle_cpus */
    sch$gl_idle_cpus=sch$gl_idle_cpus | (cpu->cpu$l_cpuid_mask);
    /** store null pcb and -1 pri: MISSING check why */
    /** necessary idle_task line from linux */
    next=idle_task(cpuid);
    goto skip_cap;
  } else {
Ejemplo n.º 14
0
asmlinkage void sch$resched(void) {
  int cpuid = smp_processor_id();
  struct _cpu * cpu=smp$gl_cpu_data[cpuid]; 
  struct _pcb * curpcb;
  unsigned long curpri;
  unsigned long qhead;
  int before,after;

  // lock sched db, soon
  //if (spl(IPL$_SCHED)) return;
  //    old=spl(IPL$_SCHED);
  // svpctx, do not think we need to do this here

#ifdef __x86_64__
  if (intr_blocked(IPL$_RESCHED))
    return;
  regtrap(REG_INTR,IPL$_RESCHED);
#endif

  /** spinlock sched and set ipl */
  setipl(IPL$_SCHED);
  vmslock(&SPIN_SCHED,-1);

  spin_lock_irq(&runqueue_lock); /* eventually change to sched? */

  /** get current pcb and priority */

  curpcb=cpu->cpu$l_curpcb;

  release_kernel_lock(curpcb, cpuid);

  curpri=cpu->cpu$b_cur_pri;

  /** clear bit in cpu_priority table */

  sch$al_cpu_priority[curpri]=sch$al_cpu_priority[curpri] & (~ cpu->cpu$l_cpuid_mask );

  /** if no process with this pri on any cpu, clear bit in active_priority table */

  if (!sch$al_cpu_priority[curpri])
    sch$gl_active_priority=sch$gl_active_priority & (~ (1 << (31-curpri)));

  /** now some if's remaining from linux - TODO: check if still needed */

  if (curpcb == idle_task(curpcb->pcb$l_cpu_id))
    goto out;

  if (curpcb->state==TASK_INTERRUPTIBLE)
    if (signal_pending(curpcb)) {
      curpcb->state = TASK_RUNNING;
      curpcb->pcb$w_state = SCH$C_CUR;
    }

#if 0
  if (curpcb->state!=TASK_RUNNING) {
    curpcb->pcb$w_state=SCH$C_LEF; // use here temporarily
  }
#endif

#if 0
  if (curpcb->state==TASK_RUNNING) {
#endif
#ifdef DEBUG_SCHED
    before=numproc();
    //    printcom();
    //if (curpcb==0xa018c000 && qhead==0xa018c000)
    //  panic("aieeeeeh\n");
    mycheckaddr(0);
    //if (curpcb==qhead) panic(" a panic\n");
#endif

    /** set pri bit in comqs */

    sch$gl_comqs=sch$gl_comqs | (1 << curpri);
    //    curpcb->state=TASK_INTERRUPTIBLE; /* soon SCH$C_COM ? */

    /** set state of cur pcb to COM */

    curpcb->pcb$w_state=SCH$C_COM;

    /** insert pcb at tail of comqueue */

#ifdef __i386__    
    qhead=*(unsigned long *)&sch$aq_comt[curpri];
#else
    qhead=*(unsigned long *)&sch$aq_comh[curpri][1];
#endif
    if (!task_on_comqueue(curpcb)) {
      if (curpcb==qhead) panic(" a panic\n");
      insque(curpcb,qhead);
    } else {
      panic("something\n");
    }
#ifdef DEBUG_SCHED
    mycheckaddr(42);
#endif
    /** linux leftover */
    nr_running++;
#ifdef DEBUG_SCHED
    after=numproc();
    if(after-before!=1) {
      //printk("entry qhead %x %x\n",curpcb,qhead);
      printcom();
      panic("insq2 %x %x\n",before,after);
    }
#endif

  out:
    /** clear idle_cpus to signal all idle cpus to try to reschedule */
    sch$gl_idle_cpus=0;
#if 0
  }
#endif
  /** go some intro sch$sched */
  sch$sched(1);
}
Ejemplo n.º 15
0
Archivo: tm.c Proyecto: jschiefer/bibo
/*! \param code_start start address of code to execute
    \param argc first argument passed, normally number of strings in argv
    \param argv second argument passed, normally pointer to argument pointers.
    \param priority new task's priority
    \param stack_size stack size for new task
    \return -1: fail, else tid.
    
    will return to caller in any case.
*/
tid_t kexeci(int (*code_start)(int, void**),int argc, void **argv,
	     priority_t priority, size_t stack_size, int tflags) {
    tdata_t *td;
    size_t * sp;

    // get memory
    //
    // task & stack area belong to parent task
    // they aren't freed by mm_reaper()
  
    td =malloc(sizeof(tdata_t) + stack_size);
    if (td == NULL)
    {
	free(td);
	return (tid_t)-1;
    }
    
    td->priority = priority;
    td->tflags = tflags;
    if ((tflags & T_KERNEL))
	nb_system_tasks++;
    
    sp= (size_t*) (td + 1);    
    sp+=(stack_size>>1);                // setup initial stack
    
    // when main() returns a value, it passes it in r0
    // as r0 is also the register to pass single int arguments by
    // gcc convention, we can just put the address of exit on the stack.
    
    *(--sp)=(size_t) &exit;
    
    // we have to construct a stack stub so tm_switcher,
    // systime_handler and the ROM routine can fill the 
    // right values on startup.
    
    *(--sp)=(size_t) code_start;        // entry point   < these two are for
    *(--sp)=0;                          // ccr           < rte in ROM
    *(--sp)=0;                          // r6      < pop r6 in ROM
    *(--sp)=(size_t)
	&rom_ocia_return;         // ROM return < rts in systime_handler
  
    *(--sp)=(size_t) argc;              // r0      < pop r0 in systime handler
    *(--sp)=(size_t) argv;              // r1..r3  < pop r1 in systime handler
    *(--sp)=0;
    *(--sp)=0;
    *(--sp)=(size_t)              
	&systime_tm_return;       // systime return < rts in tm_switcher
    
    *(--sp)=0;                        // r4..r6  in tm_switcher
    *(--sp)=0;
    *(--sp)=0;

    td->sp_save=sp;                   // save sp for tm_switcher
    td->tflags |= T_WAITING;          // task is ready for execution
    td->next = td->prev = td;
    
    grab_kernel_lock();
    make_running(td);
    nb_tasks++;
    release_kernel_lock();
    
    return td;
}