/*
 * Thread system initialization.
 */
void
thread_bootstrap(void)
{
    cpuarray_init(&allcpus);

    /*
     * Create the cpu structure for the bootup CPU, the one we're
     * currently running on. Assume the hardware number is 0; that
     * might be updated later by mainbus-type code. This also
     * creates a thread structure for the first thread, the one
     * that's already implicitly running when the kernel is
     * started from the bootloader.
     */
    KASSERT(CURCPU_EXISTS() == false);
    (void)cpu_create(0);
    KASSERT(CURCPU_EXISTS() == true);

    /* cpu_create() should also have set t_proc. */
    KASSERT(curcpu != NULL);
    KASSERT(curthread != NULL);
    KASSERT(curthread->t_proc != NULL);
    KASSERT(curthread->t_proc == kproc);

    /* Done */
}
Exemplo n.º 2
0
/*
 * Check if the current cpu holds the lock.
 */ 
bool
spinlock_do_i_hold(struct spinlock *lk)
{
	if (!CURCPU_EXISTS()) {
		return true;
	}

	/* Assume we can read lk_holder atomically enough for this to work */
	return (lk->lk_holder == curcpu->c_self);
}
Exemplo n.º 3
0
/*
 * Release the lock.
 */
void
spinlock_release(struct spinlock *lk)
{
	/* this must work before curcpu initialization */
	if (CURCPU_EXISTS()) {
		KASSERT(lk->lk_holder == curcpu->c_self);
	}

	lk->lk_holder = NULL;
	spinlock_data_set(&lk->lk_lock, 0);
	spllower(IPL_HIGH, IPL_NONE);
}
Exemplo n.º 4
0
Arquivo: spl.c Projeto: Adam-Koza/A3
/*
 * Raise and lower the interrupt priority level.
 *
 * Each spinlock acquisition can raise and lower the priority level
 * independently. The spl calls also raise and lower the priority
 * level independently of the spinlocks. This is necessary because in
 * general spinlock acquisitions and releases don't nest perfectly,
 * and don't necessarily nest with respect to spl calls either.
 *
 * For example:
 *
 *    struct spinlock red, blue;
 *    int s;
 *
 *    spinlock_acquire(&red);
 *    s = splhigh();
 *    spinlock_acquire(&blue);
 *    splx(s);
 *    spinlock_release(&red);
 *    spinlock_release(&blue);
 *
 * In order to make this work we need to count the number of times
 * IPL_HIGH (or, if we had multiple interrupt priority levels, each
 * level independently) has been raised. Interrupts go off on the
 * first raise, and go on again only on the last lower.
 *
 * curthread->t_iplhigh_count is used to track this.
 */
void
splraise(int oldspl, int newspl)
{
	struct thread *cur = curthread;

	/* only one priority level, only one valid args configuration */
	KASSERT(oldspl == IPL_NONE);
	KASSERT(newspl == IPL_HIGH);

	if (!CURCPU_EXISTS()) {
		/* before curcpu initialization; interrupts are off anyway */
		return;
	}

	if (cur->t_iplhigh_count == 0) {
		cpu_irqoff();
	}
	cur->t_iplhigh_count++;
}
Exemplo n.º 5
0
bool
lock_do_i_hold(struct lock *lock)
{
        // Write this
	if (!CURCPU_EXISTS()) {
			return true;
		}
//	if(lock->lk_holder== curcpu->c_self){
//		return true;
//	}
	//KASSERT(lock->lk_thread != NULL);
	//KASSERT(lock != NULL);
	bool value= false;

        //(void)lock;  // suppress warning until code gets written
	spinlock_acquire(&lock->lk_spinlock);
        value= (lock->lk_thread== curthread); // dummy until code gets written
        spinlock_release(&lock->lk_spinlock);
        return value;
}
Exemplo n.º 6
0
/*
 * Get the lock.
 *
 * First disable interrupts (otherwise, if we get a timer interrupt we
 * might come back to this lock and deadlock), then use a machine-level
 * atomic operation to wait for the lock to be free.
 */
void
spinlock_acquire(struct spinlock *lk)
{
	struct cpu *mycpu;

	splraise(IPL_NONE, IPL_HIGH);

	/* this must work before curcpu initialization */
	if (CURCPU_EXISTS()) {
		mycpu = curcpu->c_self;
		if (lk->lk_holder == mycpu) {
			panic("Deadlock on spinlock %p\n", lk);
		}
	}
	else {
		mycpu = NULL;
	}

	while (1) {
		/*
		 * Do test-test-and-set, that is, read first before
		 * doing test-and-set, to reduce bus contention.
		 *
		 * Test-and-set is a machine-level atomic operation
		 * that writes 1 into the lock word and returns the
		 * previous value. If that value was 0, the lock was
		 * previously unheld and we now own it. If it was 1,
		 * we don't.
		 */
		if (spinlock_data_get(&lk->lk_lock) != 0) {
			continue;
		}
		if (spinlock_data_testandset(&lk->lk_lock) != 0) {
			continue;
		}
		break;
	}

	lk->lk_holder = mycpu;
}
/*
 * Create a CPU structure. This is used for the bootup CPU and
 * also for secondary CPUs.
 *
 * The hardware number (the number assigned by firmware or system
 * board config or whatnot) is tracked separately because it is not
 * necessarily anything sane or meaningful.
 */
struct cpu *
cpu_create(unsigned hardware_number)
{
    struct cpu *c;
    int result;
    char namebuf[16];

    c = kmalloc(sizeof(*c));
    if (c == NULL) {
        panic("cpu_create: Out of memory\n");
    }

    c->c_self = c;
    c->c_hardware_number = hardware_number;

    c->c_curthread = NULL;
    threadlist_init(&c->c_zombies);
    c->c_hardclocks = 0;
    c->c_spinlocks = 0;

    c->c_isidle = false;
    threadlist_init(&c->c_runqueue);
    spinlock_init(&c->c_runqueue_lock);

    c->c_ipi_pending = 0;
    c->c_numshootdown = 0;
    spinlock_init(&c->c_ipi_lock);

    result = cpuarray_add(&allcpus, c, &c->c_number);
    if (result != 0) {
        panic("cpu_create: array_add: %s\n", strerror(result));
    }

    snprintf(namebuf, sizeof(namebuf), "<boot #%d>", c->c_number);
    c->c_curthread = thread_create(namebuf);
    if (c->c_curthread == NULL) {
        panic("cpu_create: thread_create failed\n");
    }
    c->c_curthread->t_cpu = c;

    if (c->c_number == 0) {
        /*
         * Leave c->c_curthread->t_stack NULL for the boot
         * cpu. This means we're using the boot stack, which
         * can't be freed. (Exercise: what would it take to
         * make it possible to free the boot stack?)
         */
        /*c->c_curthread->t_stack = ... */
    }
    else {
        c->c_curthread->t_stack = kmalloc(STACK_SIZE);
        if (c->c_curthread->t_stack == NULL) {
            panic("cpu_create: couldn't allocate stack");
        }
        thread_checkstack_init(c->c_curthread);
    }

    /*
     * If there is no curcpu (or curthread) yet, we are creating
     * the first (boot) cpu. Initialize curcpu and curthread as
     * early as possible so that other code can take locks without
     * exploding.
     */
    if (!CURCPU_EXISTS()) {
        /*
         * Initializing curcpu and curthread is
         * machine-dependent because either of curcpu and
         * curthread might be defined in terms of the other.
         */
        INIT_CURCPU(c, c->c_curthread);

        /*
         * Now make sure both t_cpu and c_curthread are
         * set. This might be partially redundant with
         * INIT_CURCPU depending on how things are defined.
         */
        curthread->t_cpu = curcpu;
        curcpu->c_curthread = curthread;
    }

    result = proc_addthread(kproc, c->c_curthread);
    if (result) {
        panic("cpu_create: proc_addthread:: %s\n", strerror(result));
    }

    cpu_machdep_init(c);

    return c;
}