The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/acpica/Osd/OsdSynch.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2000 Michael Smith
    3  * Copyright (c) 2000 BSDi
    4  * Copyright (c) 2007-2009 Jung-uk Kim <jkim@FreeBSD.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * 6.1 : Mutual Exclusion and Synchronisation
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD: releng/9.2/sys/dev/acpica/Osd/OsdSynch.c 249132 2013-04-05 08:22:11Z mav $");
   35 
   36 #include <contrib/dev/acpica/include/acpi.h>
   37 #include <contrib/dev/acpica/include/accommon.h>
   38 
   39 #include <sys/condvar.h>
   40 #include <sys/kernel.h>
   41 #include <sys/lock.h>
   42 #include <sys/malloc.h>
   43 #include <sys/mutex.h>
   44 
   45 #define _COMPONENT      ACPI_OS_SERVICES
   46 ACPI_MODULE_NAME("SYNCH")
   47 
   48 static MALLOC_DEFINE(M_ACPISEM, "acpisem", "ACPI semaphore");
   49 
   50 /*
   51  * Convert milliseconds to ticks.
   52  */
   53 static int
   54 timeout2hz(UINT16 Timeout)
   55 {
   56         struct timeval          tv;
   57 
   58         tv.tv_sec = (time_t)(Timeout / 1000);
   59         tv.tv_usec = (suseconds_t)(Timeout % 1000) * 1000;
   60 
   61         return (tvtohz(&tv));
   62 }
   63 
   64 /*
   65  * ACPI_SEMAPHORE
   66  */
   67 struct acpi_sema {
   68         struct mtx      as_lock;
   69         char            as_name[32];
   70         struct cv       as_cv;
   71         UINT32          as_maxunits;
   72         UINT32          as_units;
   73         int             as_waiters;
   74         int             as_reset;
   75 };
   76 
   77 ACPI_STATUS
   78 AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits,
   79     ACPI_SEMAPHORE *OutHandle)
   80 {
   81         struct acpi_sema        *as;
   82 
   83         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
   84 
   85         if (OutHandle == NULL || MaxUnits == 0 || InitialUnits > MaxUnits)
   86                 return_ACPI_STATUS (AE_BAD_PARAMETER);
   87 
   88         if ((as = malloc(sizeof(*as), M_ACPISEM, M_NOWAIT | M_ZERO)) == NULL)
   89                 return_ACPI_STATUS (AE_NO_MEMORY);
   90 
   91         snprintf(as->as_name, sizeof(as->as_name), "ACPI sema (%p)", as);
   92         mtx_init(&as->as_lock, as->as_name, NULL, MTX_DEF);
   93         cv_init(&as->as_cv, as->as_name);
   94         as->as_maxunits = MaxUnits;
   95         as->as_units = InitialUnits;
   96 
   97         *OutHandle = (ACPI_SEMAPHORE)as;
   98 
   99         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "created %s, max %u, initial %u\n",
  100             as->as_name, MaxUnits, InitialUnits));
  101 
  102         return_ACPI_STATUS (AE_OK);
  103 }
  104 
  105 ACPI_STATUS
  106 AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle)
  107 {
  108         struct acpi_sema        *as = (struct acpi_sema *)Handle;
  109 
  110         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  111 
  112         if (as == NULL)
  113                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  114 
  115         mtx_lock(&as->as_lock);
  116 
  117         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "delete %s\n", as->as_name));
  118 
  119         if (as->as_waiters > 0) {
  120                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  121                     "reset %s, units %u, waiters %d\n",
  122                     as->as_name, as->as_units, as->as_waiters));
  123                 as->as_reset = 1;
  124                 cv_broadcast(&as->as_cv);
  125                 while (as->as_waiters > 0) {
  126                         if (mtx_sleep(&as->as_reset, &as->as_lock,
  127                             PCATCH, "acsrst", hz) == EINTR) {
  128                                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  129                                     "failed to reset %s, waiters %d\n",
  130                                     as->as_name, as->as_waiters));
  131                                 mtx_unlock(&as->as_lock);
  132                                 return_ACPI_STATUS (AE_ERROR);
  133                         }
  134                         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  135                             "wait %s, units %u, waiters %d\n",
  136                             as->as_name, as->as_units, as->as_waiters));
  137                 }
  138         }
  139 
  140         mtx_unlock(&as->as_lock);
  141 
  142         mtx_destroy(&as->as_lock);
  143         cv_destroy(&as->as_cv);
  144         free(as, M_ACPISEM);
  145 
  146         return_ACPI_STATUS (AE_OK);
  147 }
  148 
  149 #define ACPISEM_AVAIL(s, u)     ((s)->as_units >= (u))
  150 
  151 ACPI_STATUS
  152 AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout)
  153 {
  154         struct acpi_sema        *as = (struct acpi_sema *)Handle;
  155         int                     error, prevtick, slptick, tmo;
  156         ACPI_STATUS             status = AE_OK;
  157 
  158         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  159 
  160         if (as == NULL || Units == 0)
  161                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  162 
  163         mtx_lock(&as->as_lock);
  164 
  165         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  166             "get %u unit(s) from %s, units %u, waiters %d, timeout %u\n",
  167             Units, as->as_name, as->as_units, as->as_waiters, Timeout));
  168 
  169         if (as->as_maxunits != ACPI_NO_UNIT_LIMIT && as->as_maxunits < Units) {
  170                 mtx_unlock(&as->as_lock);
  171                 return_ACPI_STATUS (AE_LIMIT);
  172         }
  173 
  174         switch (Timeout) {
  175         case ACPI_DO_NOT_WAIT:
  176                 if (!ACPISEM_AVAIL(as, Units))
  177                         status = AE_TIME;
  178                 break;
  179         case ACPI_WAIT_FOREVER:
  180                 while (!ACPISEM_AVAIL(as, Units)) {
  181                         as->as_waiters++;
  182                         error = cv_wait_sig(&as->as_cv, &as->as_lock);
  183                         as->as_waiters--;
  184                         if (error == EINTR || as->as_reset) {
  185                                 status = AE_ERROR;
  186                                 break;
  187                         }
  188                 }
  189                 break;
  190         default:
  191                 tmo = timeout2hz(Timeout);
  192                 while (!ACPISEM_AVAIL(as, Units)) {
  193                         prevtick = ticks;
  194                         as->as_waiters++;
  195                         error = cv_timedwait_sig(&as->as_cv, &as->as_lock, tmo);
  196                         as->as_waiters--;
  197                         if (error == EINTR || as->as_reset) {
  198                                 status = AE_ERROR;
  199                                 break;
  200                         }
  201                         if (ACPISEM_AVAIL(as, Units))
  202                                 break;
  203                         slptick = ticks - prevtick;
  204                         if (slptick >= tmo || slptick < 0) {
  205                                 status = AE_TIME;
  206                                 break;
  207                         }
  208                         tmo -= slptick;
  209                 }
  210         }
  211         if (status == AE_OK)
  212                 as->as_units -= Units;
  213 
  214         mtx_unlock(&as->as_lock);
  215 
  216         return_ACPI_STATUS (status);
  217 }
  218 
  219 ACPI_STATUS
  220 AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
  221 {
  222         struct acpi_sema        *as = (struct acpi_sema *)Handle;
  223         UINT32                  i;
  224 
  225         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  226 
  227         if (as == NULL || Units == 0)
  228                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  229 
  230         mtx_lock(&as->as_lock);
  231 
  232         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  233             "return %u units to %s, units %u, waiters %d\n",
  234             Units, as->as_name, as->as_units, as->as_waiters));
  235 
  236         if (as->as_maxunits != ACPI_NO_UNIT_LIMIT &&
  237             (as->as_maxunits < Units ||
  238             as->as_maxunits - Units < as->as_units)) {
  239                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  240                     "exceeded max units %u\n", as->as_maxunits));
  241                 mtx_unlock(&as->as_lock);
  242                 return_ACPI_STATUS (AE_LIMIT);
  243         }
  244 
  245         as->as_units += Units;
  246         if (as->as_waiters > 0 && ACPISEM_AVAIL(as, Units))
  247                 for (i = 0; i < Units; i++)
  248                         cv_signal(&as->as_cv);
  249 
  250         mtx_unlock(&as->as_lock);
  251 
  252         return_ACPI_STATUS (AE_OK);
  253 }
  254 
  255 #undef ACPISEM_AVAIL
  256 
  257 /*
  258  * ACPI_MUTEX
  259  */
  260 struct acpi_mutex {
  261         struct mtx      am_lock;
  262         char            am_name[32];
  263         struct thread   *am_owner;
  264         int             am_nested;
  265         int             am_waiters;
  266         int             am_reset;
  267 };
  268 
  269 ACPI_STATUS
  270 AcpiOsCreateMutex(ACPI_MUTEX *OutHandle)
  271 {
  272         struct acpi_mutex       *am;
  273 
  274         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  275 
  276         if (OutHandle == NULL)
  277                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  278 
  279         if ((am = malloc(sizeof(*am), M_ACPISEM, M_NOWAIT | M_ZERO)) == NULL)
  280                 return_ACPI_STATUS (AE_NO_MEMORY);
  281 
  282         snprintf(am->am_name, sizeof(am->am_name), "ACPI mutex (%p)", am);
  283         mtx_init(&am->am_lock, am->am_name, NULL, MTX_DEF);
  284 
  285         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "created %s\n", am->am_name));
  286 
  287         *OutHandle = (ACPI_MUTEX)am;
  288 
  289         return_ACPI_STATUS (AE_OK);
  290 }
  291 
  292 #define ACPIMTX_AVAIL(m)        ((m)->am_owner == NULL)
  293 #define ACPIMTX_OWNED(m)        ((m)->am_owner == curthread)
  294 
  295 void
  296 AcpiOsDeleteMutex(ACPI_MUTEX Handle)
  297 {
  298         struct acpi_mutex       *am = (struct acpi_mutex *)Handle;
  299 
  300         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  301 
  302         if (am == NULL) {
  303                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "cannot delete null mutex\n"));
  304                 return_VOID;
  305         }
  306 
  307         mtx_lock(&am->am_lock);
  308 
  309         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "delete %s\n", am->am_name));
  310 
  311         if (am->am_waiters > 0) {
  312                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  313                     "reset %s, owner %p\n", am->am_name, am->am_owner));
  314                 am->am_reset = 1;
  315                 wakeup(am);
  316                 while (am->am_waiters > 0) {
  317                         if (mtx_sleep(&am->am_reset, &am->am_lock,
  318                             PCATCH, "acmrst", hz) == EINTR) {
  319                                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  320                                     "failed to reset %s, waiters %d\n",
  321                                     am->am_name, am->am_waiters));
  322                                 mtx_unlock(&am->am_lock);
  323                                 return_VOID;
  324                         }
  325                         if (ACPIMTX_AVAIL(am))
  326                                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  327                                     "wait %s, waiters %d\n",
  328                                     am->am_name, am->am_waiters));
  329                         else
  330                                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  331                                     "wait %s, owner %p, waiters %d\n",
  332                                     am->am_name, am->am_owner, am->am_waiters));
  333                 }
  334         }
  335 
  336         mtx_unlock(&am->am_lock);
  337 
  338         mtx_destroy(&am->am_lock);
  339         free(am, M_ACPISEM);
  340 }
  341 
  342 ACPI_STATUS
  343 AcpiOsAcquireMutex(ACPI_MUTEX Handle, UINT16 Timeout)
  344 {
  345         struct acpi_mutex       *am = (struct acpi_mutex *)Handle;
  346         int                     error, prevtick, slptick, tmo;
  347         ACPI_STATUS             status = AE_OK;
  348 
  349         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  350 
  351         if (am == NULL)
  352                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  353 
  354         mtx_lock(&am->am_lock);
  355 
  356         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "acquire %s\n", am->am_name));
  357 
  358         if (ACPIMTX_OWNED(am)) {
  359                 am->am_nested++;
  360                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  361                     "acquire nested %s, depth %d\n",
  362                     am->am_name, am->am_nested));
  363                 mtx_unlock(&am->am_lock);
  364                 return_ACPI_STATUS (AE_OK);
  365         }
  366 
  367         switch (Timeout) {
  368         case ACPI_DO_NOT_WAIT:
  369                 if (!ACPIMTX_AVAIL(am))
  370                         status = AE_TIME;
  371                 break;
  372         case ACPI_WAIT_FOREVER:
  373                 while (!ACPIMTX_AVAIL(am)) {
  374                         am->am_waiters++;
  375                         error = mtx_sleep(am, &am->am_lock, PCATCH, "acmtx", 0);
  376                         am->am_waiters--;
  377                         if (error == EINTR || am->am_reset) {
  378                                 status = AE_ERROR;
  379                                 break;
  380                         }
  381                 }
  382                 break;
  383         default:
  384                 tmo = timeout2hz(Timeout);
  385                 while (!ACPIMTX_AVAIL(am)) {
  386                         prevtick = ticks;
  387                         am->am_waiters++;
  388                         error = mtx_sleep(am, &am->am_lock, PCATCH,
  389                             "acmtx", tmo);
  390                         am->am_waiters--;
  391                         if (error == EINTR || am->am_reset) {
  392                                 status = AE_ERROR;
  393                                 break;
  394                         }
  395                         if (ACPIMTX_AVAIL(am))
  396                                 break;
  397                         slptick = ticks - prevtick;
  398                         if (slptick >= tmo || slptick < 0) {
  399                                 status = AE_TIME;
  400                                 break;
  401                         }
  402                         tmo -= slptick;
  403                 }
  404         }
  405         if (status == AE_OK)
  406                 am->am_owner = curthread;
  407 
  408         mtx_unlock(&am->am_lock);
  409 
  410         return_ACPI_STATUS (status);
  411 }
  412 
  413 void
  414 AcpiOsReleaseMutex(ACPI_MUTEX Handle)
  415 {
  416         struct acpi_mutex       *am = (struct acpi_mutex *)Handle;
  417 
  418         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  419 
  420         if (am == NULL) {
  421                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  422                     "cannot release null mutex\n"));
  423                 return_VOID;
  424         }
  425 
  426         mtx_lock(&am->am_lock);
  427 
  428         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "release %s\n", am->am_name));
  429 
  430         if (ACPIMTX_OWNED(am)) {
  431                 if (am->am_nested > 0) {
  432                         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  433                             "release nested %s, depth %d\n",
  434                             am->am_name, am->am_nested));
  435                         am->am_nested--;
  436                 } else
  437                         am->am_owner = NULL;
  438         } else {
  439                 if (ACPIMTX_AVAIL(am))
  440                         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  441                             "release already available %s\n", am->am_name));
  442                 else
  443                         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  444                             "release unowned %s from %p, depth %d\n",
  445                             am->am_name, am->am_owner, am->am_nested));
  446         }
  447         if (am->am_waiters > 0 && ACPIMTX_AVAIL(am))
  448                 wakeup_one(am);
  449 
  450         mtx_unlock(&am->am_lock);
  451 }
  452 
  453 #undef ACPIMTX_AVAIL
  454 #undef ACPIMTX_OWNED
  455 
  456 /*
  457  * ACPI_SPINLOCK
  458  */
  459 struct acpi_spinlock {
  460         struct mtx      al_lock;
  461         char            al_name[32];
  462         int             al_nested;
  463 };
  464 
  465 ACPI_STATUS
  466 AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle)
  467 {
  468         struct acpi_spinlock    *al;
  469 
  470         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  471 
  472         if (OutHandle == NULL)
  473                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  474 
  475         if ((al = malloc(sizeof(*al), M_ACPISEM, M_NOWAIT | M_ZERO)) == NULL)
  476                 return_ACPI_STATUS (AE_NO_MEMORY);
  477 
  478 #ifdef ACPI_DEBUG
  479         if (OutHandle == &AcpiGbl_GpeLock)
  480                 snprintf(al->al_name, sizeof(al->al_name), "ACPI lock (GPE)");
  481         else if (OutHandle == &AcpiGbl_HardwareLock)
  482                 snprintf(al->al_name, sizeof(al->al_name), "ACPI lock (HW)");
  483         else
  484 #endif
  485         snprintf(al->al_name, sizeof(al->al_name), "ACPI lock (%p)", al);
  486         mtx_init(&al->al_lock, al->al_name, NULL, MTX_SPIN);
  487 
  488         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "created %s\n", al->al_name));
  489 
  490         *OutHandle = (ACPI_SPINLOCK)al;
  491 
  492         return_ACPI_STATUS (AE_OK);
  493 }
  494 
  495 void
  496 AcpiOsDeleteLock(ACPI_SPINLOCK Handle)
  497 {
  498         struct acpi_spinlock    *al = (struct acpi_spinlock *)Handle;
  499 
  500         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  501 
  502         if (al == NULL) {
  503                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  504                     "cannot delete null spinlock\n"));
  505                 return_VOID;
  506         }
  507 
  508         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "delete %s\n", al->al_name));
  509 
  510         mtx_destroy(&al->al_lock);
  511         free(al, M_ACPISEM);
  512 }
  513 
  514 ACPI_CPU_FLAGS
  515 AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
  516 {
  517         struct acpi_spinlock    *al = (struct acpi_spinlock *)Handle;
  518 
  519         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  520 
  521         if (al == NULL) {
  522                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  523                     "cannot acquire null spinlock\n"));
  524                 return (0);
  525         }
  526 
  527         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "acquire %s\n", al->al_name));
  528 
  529         if (mtx_owned(&al->al_lock)) {
  530                 al->al_nested++;
  531                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  532                     "acquire nested %s, depth %d\n",
  533                     al->al_name, al->al_nested));
  534         } else
  535                 mtx_lock_spin(&al->al_lock);
  536 
  537         return (0);
  538 }
  539 
  540 void
  541 AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
  542 {
  543         struct acpi_spinlock    *al = (struct acpi_spinlock *)Handle;
  544 
  545         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  546 
  547         if (al == NULL) {
  548                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  549                     "cannot release null spinlock\n"));
  550                 return_VOID;
  551         }
  552 
  553         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "release %s\n", al->al_name));
  554 
  555         if (mtx_owned(&al->al_lock)) {
  556                 if (al->al_nested > 0) {
  557                         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  558                             "release nested %s, depth %d\n",
  559                             al->al_name, al->al_nested));
  560                         al->al_nested--;
  561                 } else
  562                         mtx_unlock_spin(&al->al_lock);
  563         } else
  564                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  565                     "cannot release unowned %s\n", al->al_name));
  566 }
  567 
  568 /* Section 5.2.10.1: global lock acquire/release functions */
  569 #define GL_BIT_PENDING  0x01
  570 #define GL_BIT_OWNED    0x02
  571 
  572 /*
  573  * Acquire the global lock.  If busy, set the pending bit.  The caller
  574  * will wait for notification from the BIOS that the lock is available
  575  * and then attempt to acquire it again.
  576  */
  577 int
  578 acpi_acquire_global_lock(uint32_t *lock)
  579 {
  580         uint32_t        new, old;
  581 
  582         do {
  583                 old = *lock;
  584                 new = (old & ~GL_BIT_PENDING) | GL_BIT_OWNED;
  585                 if ((old & GL_BIT_OWNED) != 0)
  586                         new |= GL_BIT_PENDING;
  587         } while (atomic_cmpset_acq_int(lock, old, new) == 0);
  588 
  589         return ((new & GL_BIT_PENDING) == 0);
  590 }
  591 
  592 /*
  593  * Release the global lock, returning whether there is a waiter pending.
  594  * If the BIOS set the pending bit, OSPM must notify the BIOS when it
  595  * releases the lock.
  596  */
  597 int
  598 acpi_release_global_lock(uint32_t *lock)
  599 {
  600         uint32_t        new, old;
  601 
  602         do {
  603                 old = *lock;
  604                 new = old & ~(GL_BIT_PENDING | GL_BIT_OWNED);
  605         } while (atomic_cmpset_rel_int(lock, old, new) == 0);
  606 
  607         return ((old & GL_BIT_PENDING) != 0);
  608 }

Cache object: 5b94cad196ec204dc68a772f5b062a25


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.