/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file contains the semaphore operations.
*/
#include <sys/schedctl.h>
#include <sys/semaphore.h>
#include <sys/sema_impl.h>
static void sema_unsleep(kthread_t *t);
/*
* The sobj_ops vector exports a set of functions needed when a thread
* is asleep on a synchronization object of this type.
*/
};
/*
* SEMA_BLOCK(sema_impl_t *s, disp_lock_t *lockp)
*/
{ \
DTRACE_SCHED(sleep); \
} \
break; \
} \
}
/* ARGSUSED */
void
{
}
void
{
}
/*
* Put a thread on the sleep queue for this semaphore.
*/
static void
{
sema_impl_t *s;
ASSERT(THREAD_LOCK_HELD(t));
s = (sema_impl_t *)sp;
break;
}
*tpp = t;
}
/*
* Remove a thread from the sleep queue for this
* semaphore.
*/
static void
{
sema_impl_t *s;
ASSERT(THREAD_LOCK_HELD(t));
s = (sema_impl_t *)sp;
if (tp == t) {
return;
}
}
}
/* ARGSUSED */
static kthread_t *
{
}
/*
* Wakeup a thread sleeping on a semaphore, and put it
* on the dispatch queue.
* Called via SOBJ_UNSLEEP().
*/
static void
{
sema_impl_t *s;
ASSERT(THREAD_LOCK_HELD(t));
s = (sema_impl_t *)t->t_wchan;
if (tp == t) {
t->t_sobj_ops = NULL;
/*
* Change thread to transition state and
* drop the semaphore sleep queue lock.
*/
CL_SETRUN(t);
return;
}
}
}
/*
* operations to perform when changing the priority
* of a thread asleep on a semaphore.
* Called via SOBJ_CHANGE_PRI() and SOBJ_CHANGE_EPRI().
*/
static void
{
sema_dequeue(sp, t);
sema_queue(sp, t);
} else
panic("sema_change_pri: %p not on sleep queue", (void *)t);
}
/*
* the semaphore is granted when the semaphore's
* count is greater than zero and blocks when equal
* to zero.
*/
void
{
sema_impl_t *s;
s = (sema_impl_t *)sp;
while (s->s_count == 0) {
if (panicstr) {
return;
}
SEMA_BLOCK(s, sqlp);
swtch();
}
s->s_count--;
}
/*
* similiar to sema_p except that it blocks at an interruptible
* priority. if a signal is present then return 1 otherwise 0.
*/
int
{
int cancel_pending;
int cancelled = 0;
sema_impl_t *s;
return (0);
}
s = (sema_impl_t *)sp;
while (s->s_count == 0) {
thread_lock_high(t);
t->t_flag |= T_WAKEABLE;
SEMA_BLOCK(s, sqlp);
lwp->lwp_sysabort = 0;
setrun(t);
swtch();
t->t_flag &= ~T_WAKEABLE;
lwp->lwp_asleep = 0;
lwp->lwp_sysabort = 0;
/*
* in case sema_v and interrupt happen
* at the same time, we need to pass the
* sema_v to the next thread.
*/
} else {
}
if (cancelled)
return (1);
}
lwp->lwp_asleep = 0;
}
s->s_count--;
return (0);
}
/*
* the semaphore's count is incremented by one. a blocked thread
* is awakened and re-tries to acquire the semaphore.
*/
void
{
sema_impl_t *s;
s = (sema_impl_t *)sp;
if (panicstr) {
return;
}
s->s_count++;
} else {
}
}
/*
* try to acquire the semaphore. if the semaphore is greater than
* zero, then the semaphore is granted and returns 1. otherwise
* return 0.
*/
int
{
sema_impl_t *s;
int gotit = 0;
s = (sema_impl_t *)sp;
if (s->s_count > 0) {
s->s_count--;
gotit = 1;
}
return (gotit);
}
int
{
sema_impl_t *s;
s = (sema_impl_t *)sp;
if (panicstr)
return (1);
else
return (s->s_count <= 0);
}