17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5d4204c85Sraf * Common Development and Distribution License (the "License"). 6d4204c85Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21d4204c85Sraf 227c478bd9Sstevel@tonic-gate /* 23d4204c85Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include "lint.h" 307c478bd9Sstevel@tonic-gate #include "thr_uberdata.h" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate static uint32_t _semvaluemax; 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /* 357c478bd9Sstevel@tonic-gate * Check to see if anyone is waiting for this semaphore. 367c478bd9Sstevel@tonic-gate */ 377257d1b4Sraf #pragma weak _sema_held = sema_held 387c478bd9Sstevel@tonic-gate int 397257d1b4Sraf sema_held(sema_t *sp) 407c478bd9Sstevel@tonic-gate { 417c478bd9Sstevel@tonic-gate return (sp->count == 0); 427c478bd9Sstevel@tonic-gate } 437c478bd9Sstevel@tonic-gate 447257d1b4Sraf #pragma weak _sema_init = sema_init 457257d1b4Sraf /* ARGSUSED3 */ 467c478bd9Sstevel@tonic-gate int 477257d1b4Sraf sema_init(sema_t *sp, unsigned int count, int type, void *arg) 487c478bd9Sstevel@tonic-gate { 497c478bd9Sstevel@tonic-gate if (_semvaluemax == 0) 507c478bd9Sstevel@tonic-gate _semvaluemax = (uint32_t)_sysconf(_SC_SEM_VALUE_MAX); 517c478bd9Sstevel@tonic-gate if ((type != USYNC_THREAD && type != USYNC_PROCESS) || 527c478bd9Sstevel@tonic-gate (count > _semvaluemax)) 537c478bd9Sstevel@tonic-gate return (EINVAL); 548cd45542Sraf (void) memset(sp, 0, sizeof (*sp)); 557c478bd9Sstevel@tonic-gate sp->count = count; 567c478bd9Sstevel@tonic-gate sp->type = (uint16_t)type; 577c478bd9Sstevel@tonic-gate sp->magic = SEMA_MAGIC; 58*7c5714f6Sraf 59*7c5714f6Sraf /* 60*7c5714f6Sraf * This should be at the beginning of the function, 61*7c5714f6Sraf * but for the sake of old broken applications that 62*7c5714f6Sraf * do not have proper alignment for their semaphores 63*7c5714f6Sraf * (and don't check the return code from sema_init), 64*7c5714f6Sraf * we put it here, after initializing the semaphore regardless. 65*7c5714f6Sraf */ 66*7c5714f6Sraf if (((uintptr_t)sp & (_LONG_LONG_ALIGNMENT - 1)) && 67*7c5714f6Sraf curthread->ul_misaligned == 0) 68*7c5714f6Sraf return (EINVAL); 69*7c5714f6Sraf 707c478bd9Sstevel@tonic-gate return (0); 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate 737257d1b4Sraf #pragma weak _sema_destroy = sema_destroy 747c478bd9Sstevel@tonic-gate int 757257d1b4Sraf sema_destroy(sema_t *sp) 767c478bd9Sstevel@tonic-gate { 777c478bd9Sstevel@tonic-gate sp->magic = 0; 787c478bd9Sstevel@tonic-gate tdb_sync_obj_deregister(sp); 797c478bd9Sstevel@tonic-gate return (0); 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate static int 837c478bd9Sstevel@tonic-gate sema_wait_impl(sema_t *sp, timespec_t *tsp) 847c478bd9Sstevel@tonic-gate { 857c478bd9Sstevel@tonic-gate lwp_sema_t *lsp = (lwp_sema_t *)sp; 867c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 877c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 887c478bd9Sstevel@tonic-gate tdb_sema_stats_t *ssp = SEMA_STATS(sp, udp); 897c478bd9Sstevel@tonic-gate hrtime_t begin_sleep = 0; 907c478bd9Sstevel@tonic-gate uint_t count; 917c478bd9Sstevel@tonic-gate int error = 0; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* 947c478bd9Sstevel@tonic-gate * All variations of sema_wait() are cancellation points. 957c478bd9Sstevel@tonic-gate */ 967c478bd9Sstevel@tonic-gate _cancelon(); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (ssp) 997c478bd9Sstevel@tonic-gate tdb_incr(ssp->sema_wait); 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); 1027c478bd9Sstevel@tonic-gate self->ul_wchan = lsp; 1037c478bd9Sstevel@tonic-gate if (__td_event_report(self, TD_SLEEP, udp)) { 1047c478bd9Sstevel@tonic-gate self->ul_td_evbuf.eventnum = TD_SLEEP; 1057c478bd9Sstevel@tonic-gate self->ul_td_evbuf.eventdata = lsp; 1067c478bd9Sstevel@tonic-gate tdb_event(TD_SLEEP, udp); 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate /* just a guess, but it looks like we will sleep */ 1097c478bd9Sstevel@tonic-gate if (ssp && lsp->count == 0) { 1107c478bd9Sstevel@tonic-gate begin_sleep = gethrtime(); 1117c478bd9Sstevel@tonic-gate if (lsp->count == 0) /* still looks like sleep */ 1127c478bd9Sstevel@tonic-gate tdb_incr(ssp->sema_wait_sleep); 1137c478bd9Sstevel@tonic-gate else /* we changed our mind */ 1147c478bd9Sstevel@tonic-gate begin_sleep = 0; 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate if (lsp->type == USYNC_PROCESS) { /* kernel-level */ 1187c478bd9Sstevel@tonic-gate set_parking_flag(self, 1); 1197c478bd9Sstevel@tonic-gate if (self->ul_cursig != 0 || 1207c478bd9Sstevel@tonic-gate (self->ul_cancelable && self->ul_cancel_pending)) 1217c478bd9Sstevel@tonic-gate set_parking_flag(self, 0); 1227c478bd9Sstevel@tonic-gate /* the kernel always does FIFO queueing */ 1237c478bd9Sstevel@tonic-gate error = ___lwp_sema_timedwait(lsp, tsp, 1); 1247c478bd9Sstevel@tonic-gate set_parking_flag(self, 0); 1257c478bd9Sstevel@tonic-gate } else if (!udp->uberflags.uf_mt && /* single threaded */ 1267c478bd9Sstevel@tonic-gate lsp->count != 0) { /* and non-blocking */ 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate * Since we are single-threaded, we don't need the 1297c478bd9Sstevel@tonic-gate * protection of queue_lock(). However, we do need 1307c478bd9Sstevel@tonic-gate * to block signals while modifying the count. 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate sigoff(self); 1337c478bd9Sstevel@tonic-gate lsp->count--; 1347c478bd9Sstevel@tonic-gate sigon(self); 1357c478bd9Sstevel@tonic-gate } else { /* multithreaded or blocking */ 1367c478bd9Sstevel@tonic-gate queue_head_t *qp; 1377c478bd9Sstevel@tonic-gate ulwp_t *ulwp; 1387c478bd9Sstevel@tonic-gate lwpid_t lwpid = 0; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate qp = queue_lock(lsp, CV); 1417c478bd9Sstevel@tonic-gate while (error == 0 && lsp->count == 0) { 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * SUSV3 requires FIFO queueing for semaphores, 1447c478bd9Sstevel@tonic-gate * at least for SCHED_FIFO and SCHED_RR scheduling. 1457c478bd9Sstevel@tonic-gate */ 146d4204c85Sraf enqueue(qp, self, 1); 1477c478bd9Sstevel@tonic-gate lsp->sema_waiters = 1; 1487c478bd9Sstevel@tonic-gate set_parking_flag(self, 1); 1497c478bd9Sstevel@tonic-gate queue_unlock(qp); 1507c478bd9Sstevel@tonic-gate /* 1517c478bd9Sstevel@tonic-gate * We may have received SIGCANCEL before we 1527c478bd9Sstevel@tonic-gate * called queue_lock(). If so and we are 1537c478bd9Sstevel@tonic-gate * cancelable we should return EINTR. 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate if (self->ul_cursig != 0 || 1567c478bd9Sstevel@tonic-gate (self->ul_cancelable && self->ul_cancel_pending)) 1577c478bd9Sstevel@tonic-gate set_parking_flag(self, 0); 1587c478bd9Sstevel@tonic-gate error = __lwp_park(tsp, 0); 1597c478bd9Sstevel@tonic-gate set_parking_flag(self, 0); 1607c478bd9Sstevel@tonic-gate qp = queue_lock(lsp, CV); 1617c478bd9Sstevel@tonic-gate if (self->ul_sleepq) /* timeout or spurious wakeup */ 162d4204c85Sraf lsp->sema_waiters = dequeue_self(qp); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate if (error == 0) 1657c478bd9Sstevel@tonic-gate lsp->count--; 1667c478bd9Sstevel@tonic-gate if (lsp->count != 0 && lsp->sema_waiters) { 167d4204c85Sraf int more; 168d4204c85Sraf if ((ulwp = dequeue(qp, &more)) != NULL) { 1697c478bd9Sstevel@tonic-gate no_preempt(self); 1707c478bd9Sstevel@tonic-gate lwpid = ulwp->ul_lwpid; 1717c478bd9Sstevel@tonic-gate } 172d4204c85Sraf lsp->sema_waiters = more; 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate queue_unlock(qp); 1757c478bd9Sstevel@tonic-gate if (lwpid) { 1767c478bd9Sstevel@tonic-gate (void) __lwp_unpark(lwpid); 1777c478bd9Sstevel@tonic-gate preempt(self); 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate self->ul_wchan = NULL; 1827c478bd9Sstevel@tonic-gate self->ul_sp = 0; 1837c478bd9Sstevel@tonic-gate if (ssp) { 1847c478bd9Sstevel@tonic-gate if (error == 0) { 1857c478bd9Sstevel@tonic-gate /* we just decremented the count */ 1867c478bd9Sstevel@tonic-gate count = lsp->count; 1877c478bd9Sstevel@tonic-gate if (ssp->sema_min_count > count) 1887c478bd9Sstevel@tonic-gate ssp->sema_min_count = count; 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate if (begin_sleep) 1917c478bd9Sstevel@tonic-gate ssp->sema_wait_sleep_time += gethrtime() - begin_sleep; 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate if (error == EINTR) 1957c478bd9Sstevel@tonic-gate _canceloff(); 1967c478bd9Sstevel@tonic-gate else 1977c478bd9Sstevel@tonic-gate _canceloff_nocancel(); 1987c478bd9Sstevel@tonic-gate return (error); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017257d1b4Sraf #pragma weak _sema_wait = sema_wait 2027c478bd9Sstevel@tonic-gate int 2037257d1b4Sraf sema_wait(sema_t *sp) 2047c478bd9Sstevel@tonic-gate { 2057c478bd9Sstevel@tonic-gate ASSERT(!curthread->ul_critical || curthread->ul_bindflags); 2067c478bd9Sstevel@tonic-gate return (sema_wait_impl(sp, NULL)); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate int 2107257d1b4Sraf sema_reltimedwait(sema_t *sp, const timespec_t *reltime) 2117c478bd9Sstevel@tonic-gate { 2127c478bd9Sstevel@tonic-gate timespec_t tslocal = *reltime; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate ASSERT(!curthread->ul_critical || curthread->ul_bindflags); 2157c478bd9Sstevel@tonic-gate return (sema_wait_impl(sp, &tslocal)); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate int 2197257d1b4Sraf sema_timedwait(sema_t *sp, const timespec_t *abstime) 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate timespec_t tslocal; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate ASSERT(!curthread->ul_critical || curthread->ul_bindflags); 2247c478bd9Sstevel@tonic-gate abstime_to_reltime(CLOCK_REALTIME, abstime, &tslocal); 2257c478bd9Sstevel@tonic-gate return (sema_wait_impl(sp, &tslocal)); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2287257d1b4Sraf #pragma weak _sema_trywait = sema_trywait 2297c478bd9Sstevel@tonic-gate int 2307257d1b4Sraf sema_trywait(sema_t *sp) 2317c478bd9Sstevel@tonic-gate { 2327c478bd9Sstevel@tonic-gate lwp_sema_t *lsp = (lwp_sema_t *)sp; 2337c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 2347c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 2357c478bd9Sstevel@tonic-gate tdb_sema_stats_t *ssp = SEMA_STATS(sp, udp); 2367c478bd9Sstevel@tonic-gate uint_t count; 2377c478bd9Sstevel@tonic-gate int error = 0; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate ASSERT(!curthread->ul_critical || curthread->ul_bindflags); 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate if (ssp) 2427c478bd9Sstevel@tonic-gate tdb_incr(ssp->sema_trywait); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (lsp->type == USYNC_PROCESS) { /* kernel-level */ 2457257d1b4Sraf error = _lwp_sema_trywait(lsp); 2467c478bd9Sstevel@tonic-gate } else if (!udp->uberflags.uf_mt) { /* single threaded */ 2477c478bd9Sstevel@tonic-gate sigoff(self); 2487c478bd9Sstevel@tonic-gate if (lsp->count == 0) 2497c478bd9Sstevel@tonic-gate error = EBUSY; 2507c478bd9Sstevel@tonic-gate else 2517c478bd9Sstevel@tonic-gate lsp->count--; 2527c478bd9Sstevel@tonic-gate sigon(self); 2537c478bd9Sstevel@tonic-gate } else { /* multithreaded */ 2547c478bd9Sstevel@tonic-gate queue_head_t *qp; 2557c478bd9Sstevel@tonic-gate ulwp_t *ulwp; 2567c478bd9Sstevel@tonic-gate lwpid_t lwpid = 0; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate qp = queue_lock(lsp, CV); 2597c478bd9Sstevel@tonic-gate if (lsp->count == 0) 2607c478bd9Sstevel@tonic-gate error = EBUSY; 2617c478bd9Sstevel@tonic-gate else if (--lsp->count != 0 && lsp->sema_waiters) { 262d4204c85Sraf int more; 263d4204c85Sraf if ((ulwp = dequeue(qp, &more)) != NULL) { 2647c478bd9Sstevel@tonic-gate no_preempt(self); 2657c478bd9Sstevel@tonic-gate lwpid = ulwp->ul_lwpid; 2667c478bd9Sstevel@tonic-gate } 267d4204c85Sraf lsp->sema_waiters = more; 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate queue_unlock(qp); 2707c478bd9Sstevel@tonic-gate if (lwpid) { 2717c478bd9Sstevel@tonic-gate (void) __lwp_unpark(lwpid); 2727c478bd9Sstevel@tonic-gate preempt(self); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (error == 0) { 2777c478bd9Sstevel@tonic-gate if (ssp) { 2787c478bd9Sstevel@tonic-gate /* we just decremented the count */ 2797c478bd9Sstevel@tonic-gate count = lsp->count; 2807c478bd9Sstevel@tonic-gate if (ssp->sema_min_count > count) 2817c478bd9Sstevel@tonic-gate ssp->sema_min_count = count; 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate } else { 2847c478bd9Sstevel@tonic-gate if (ssp) 2857c478bd9Sstevel@tonic-gate tdb_incr(ssp->sema_trywait_fail); 2867c478bd9Sstevel@tonic-gate if (__td_event_report(self, TD_LOCK_TRY, udp)) { 2877c478bd9Sstevel@tonic-gate self->ul_td_evbuf.eventnum = TD_LOCK_TRY; 2887c478bd9Sstevel@tonic-gate tdb_event(TD_LOCK_TRY, udp); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate return (error); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957257d1b4Sraf #pragma weak _sema_post = sema_post 2967c478bd9Sstevel@tonic-gate int 2977257d1b4Sraf sema_post(sema_t *sp) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate lwp_sema_t *lsp = (lwp_sema_t *)sp; 3007c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 3017c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 3027c478bd9Sstevel@tonic-gate tdb_sema_stats_t *ssp = SEMA_STATS(sp, udp); 3037c478bd9Sstevel@tonic-gate uint_t count; 3047c478bd9Sstevel@tonic-gate int error = 0; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if (ssp) 3077c478bd9Sstevel@tonic-gate tdb_incr(ssp->sema_post); 3087c478bd9Sstevel@tonic-gate if (_semvaluemax == 0) 3097c478bd9Sstevel@tonic-gate _semvaluemax = (uint32_t)_sysconf(_SC_SEM_VALUE_MAX); 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if (lsp->type == USYNC_PROCESS) { /* kernel-level */ 3127257d1b4Sraf error = _lwp_sema_post(lsp); 3137c478bd9Sstevel@tonic-gate } else if (!udp->uberflags.uf_mt) { /* single threaded */ 3147c478bd9Sstevel@tonic-gate sigoff(self); 3157c478bd9Sstevel@tonic-gate if (lsp->count >= _semvaluemax) 3167c478bd9Sstevel@tonic-gate error = EOVERFLOW; 3177c478bd9Sstevel@tonic-gate else 3187c478bd9Sstevel@tonic-gate lsp->count++; 3197c478bd9Sstevel@tonic-gate sigon(self); 3207c478bd9Sstevel@tonic-gate } else { /* multithreaded */ 3217c478bd9Sstevel@tonic-gate queue_head_t *qp; 3227c478bd9Sstevel@tonic-gate ulwp_t *ulwp; 3237c478bd9Sstevel@tonic-gate lwpid_t lwpid = 0; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate qp = queue_lock(lsp, CV); 3267c478bd9Sstevel@tonic-gate if (lsp->count >= _semvaluemax) 3277c478bd9Sstevel@tonic-gate error = EOVERFLOW; 3287c478bd9Sstevel@tonic-gate else if (lsp->count++ == 0 && lsp->sema_waiters) { 329d4204c85Sraf int more; 330d4204c85Sraf if ((ulwp = dequeue(qp, &more)) != NULL) { 3317c478bd9Sstevel@tonic-gate no_preempt(self); 3327c478bd9Sstevel@tonic-gate lwpid = ulwp->ul_lwpid; 3337c478bd9Sstevel@tonic-gate } 334d4204c85Sraf lsp->sema_waiters = more; 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate queue_unlock(qp); 3377c478bd9Sstevel@tonic-gate if (lwpid) { 3387c478bd9Sstevel@tonic-gate (void) __lwp_unpark(lwpid); 3397c478bd9Sstevel@tonic-gate preempt(self); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if (error == 0) { 3447c478bd9Sstevel@tonic-gate if (ssp) { 3457c478bd9Sstevel@tonic-gate /* we just incremented the count */ 3467c478bd9Sstevel@tonic-gate count = lsp->count; 3477c478bd9Sstevel@tonic-gate if (ssp->sema_max_count < count) 3487c478bd9Sstevel@tonic-gate ssp->sema_max_count = count; 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate return (error); 3537c478bd9Sstevel@tonic-gate } 354