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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
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: head/sys/dev/acpica/Osd/OsdSynch.c 299977 2016-05-16 21:33:31Z jhb $");
   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                 if (cold) {
  192                         /*
  193                          * Just spin polling the semaphore once a
  194                          * millisecond.
  195                          */
  196                         while (!ACPISEM_AVAIL(as, Units)) {
  197                                 if (Timeout == 0) {
  198                                         status = AE_TIME;
  199                                         break;
  200                                 }
  201                                 Timeout--;
  202                                 mtx_unlock(&as->as_lock);
  203                                 DELAY(1000);
  204                                 mtx_lock(&as->as_lock);
  205                         }
  206                         break;
  207                 }
  208                 tmo = timeout2hz(Timeout);
  209                 while (!ACPISEM_AVAIL(as, Units)) {
  210                         prevtick = ticks;
  211                         as->as_waiters++;
  212                         error = cv_timedwait_sig(&as->as_cv, &as->as_lock, tmo);
  213                         as->as_waiters--;
  214                         if (error == EINTR || as->as_reset) {
  215                                 status = AE_ERROR;
  216                                 break;
  217                         }
  218                         if (ACPISEM_AVAIL(as, Units))
  219                                 break;
  220                         slptick = ticks - prevtick;
  221                         if (slptick >= tmo || slptick < 0) {
  222                                 status = AE_TIME;
  223                                 break;
  224                         }
  225                         tmo -= slptick;
  226                 }
  227         }
  228         if (ACPI_SUCCESS(status))
  229                 as->as_units -= Units;
  230 
  231         mtx_unlock(&as->as_lock);
  232 
  233         return_ACPI_STATUS (status);
  234 }
  235 
  236 ACPI_STATUS
  237 AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
  238 {
  239         struct acpi_sema        *as = (struct acpi_sema *)Handle;
  240         UINT32                  i;
  241 
  242         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  243 
  244         if (as == NULL || Units == 0)
  245                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  246 
  247         mtx_lock(&as->as_lock);
  248 
  249         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  250             "return %u units to %s, units %u, waiters %d\n",
  251             Units, as->as_name, as->as_units, as->as_waiters));
  252 
  253         if (as->as_maxunits != ACPI_NO_UNIT_LIMIT &&
  254             (as->as_maxunits < Units ||
  255             as->as_maxunits - Units < as->as_units)) {
  256                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  257                     "exceeded max units %u\n", as->as_maxunits));
  258                 mtx_unlock(&as->as_lock);
  259                 return_ACPI_STATUS (AE_LIMIT);
  260         }
  261 
  262         as->as_units += Units;
  263         if (as->as_waiters > 0 && ACPISEM_AVAIL(as, Units))
  264                 for (i = 0; i < Units; i++)
  265                         cv_signal(&as->as_cv);
  266 
  267         mtx_unlock(&as->as_lock);
  268 
  269         return_ACPI_STATUS (AE_OK);
  270 }
  271 
  272 #undef ACPISEM_AVAIL
  273 
  274 /*
  275  * ACPI_MUTEX
  276  */
  277 struct acpi_mutex {
  278         struct mtx      am_lock;
  279         char            am_name[32];
  280         struct thread   *am_owner;
  281         int             am_nested;
  282         int             am_waiters;
  283         int             am_reset;
  284 };
  285 
  286 ACPI_STATUS
  287 AcpiOsCreateMutex(ACPI_MUTEX *OutHandle)
  288 {
  289         struct acpi_mutex       *am;
  290 
  291         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  292 
  293         if (OutHandle == NULL)
  294                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  295 
  296         if ((am = malloc(sizeof(*am), M_ACPISEM, M_NOWAIT | M_ZERO)) == NULL)
  297                 return_ACPI_STATUS (AE_NO_MEMORY);
  298 
  299         snprintf(am->am_name, sizeof(am->am_name), "ACPI mutex (%p)", am);
  300         mtx_init(&am->am_lock, am->am_name, NULL, MTX_DEF);
  301 
  302         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "created %s\n", am->am_name));
  303 
  304         *OutHandle = (ACPI_MUTEX)am;
  305 
  306         return_ACPI_STATUS (AE_OK);
  307 }
  308 
  309 #define ACPIMTX_AVAIL(m)        ((m)->am_owner == NULL)
  310 #define ACPIMTX_OWNED(m)        ((m)->am_owner == curthread)
  311 
  312 void
  313 AcpiOsDeleteMutex(ACPI_MUTEX Handle)
  314 {
  315         struct acpi_mutex       *am = (struct acpi_mutex *)Handle;
  316 
  317         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  318 
  319         if (am == NULL) {
  320                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "cannot delete null mutex\n"));
  321                 return_VOID;
  322         }
  323 
  324         mtx_lock(&am->am_lock);
  325 
  326         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "delete %s\n", am->am_name));
  327 
  328         if (am->am_waiters > 0) {
  329                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  330                     "reset %s, owner %p\n", am->am_name, am->am_owner));
  331                 am->am_reset = 1;
  332                 wakeup(am);
  333                 while (am->am_waiters > 0) {
  334                         if (mtx_sleep(&am->am_reset, &am->am_lock,
  335                             PCATCH, "acmrst", hz) == EINTR) {
  336                                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  337                                     "failed to reset %s, waiters %d\n",
  338                                     am->am_name, am->am_waiters));
  339                                 mtx_unlock(&am->am_lock);
  340                                 return_VOID;
  341                         }
  342                         if (ACPIMTX_AVAIL(am))
  343                                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  344                                     "wait %s, waiters %d\n",
  345                                     am->am_name, am->am_waiters));
  346                         else
  347                                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  348                                     "wait %s, owner %p, waiters %d\n",
  349                                     am->am_name, am->am_owner, am->am_waiters));
  350                 }
  351         }
  352 
  353         mtx_unlock(&am->am_lock);
  354 
  355         mtx_destroy(&am->am_lock);
  356         free(am, M_ACPISEM);
  357 }
  358 
  359 ACPI_STATUS
  360 AcpiOsAcquireMutex(ACPI_MUTEX Handle, UINT16 Timeout)
  361 {
  362         struct acpi_mutex       *am = (struct acpi_mutex *)Handle;
  363         int                     error, prevtick, slptick, tmo;
  364         ACPI_STATUS             status = AE_OK;
  365 
  366         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  367 
  368         if (am == NULL)
  369                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  370 
  371         mtx_lock(&am->am_lock);
  372 
  373         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "acquire %s\n", am->am_name));
  374 
  375         if (ACPIMTX_OWNED(am)) {
  376                 am->am_nested++;
  377                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  378                     "acquire nested %s, depth %d\n",
  379                     am->am_name, am->am_nested));
  380                 mtx_unlock(&am->am_lock);
  381                 return_ACPI_STATUS (AE_OK);
  382         }
  383 
  384         switch (Timeout) {
  385         case ACPI_DO_NOT_WAIT:
  386                 if (!ACPIMTX_AVAIL(am))
  387                         status = AE_TIME;
  388                 break;
  389         case ACPI_WAIT_FOREVER:
  390                 while (!ACPIMTX_AVAIL(am)) {
  391                         am->am_waiters++;
  392                         error = mtx_sleep(am, &am->am_lock, PCATCH, "acmtx", 0);
  393                         am->am_waiters--;
  394                         if (error == EINTR || am->am_reset) {
  395                                 status = AE_ERROR;
  396                                 break;
  397                         }
  398                 }
  399                 break;
  400         default:
  401                 if (cold) {
  402                         /*
  403                          * Just spin polling the mutex once a
  404                          * millisecond.
  405                          */
  406                         while (!ACPIMTX_AVAIL(am)) {
  407                                 if (Timeout == 0) {
  408                                         status = AE_TIME;
  409                                         break;
  410                                 }
  411                                 Timeout--;
  412                                 mtx_unlock(&am->am_lock);
  413                                 DELAY(1000);
  414                                 mtx_lock(&am->am_lock);
  415                         }
  416                         break;
  417                 }
  418                 tmo = timeout2hz(Timeout);
  419                 while (!ACPIMTX_AVAIL(am)) {
  420                         prevtick = ticks;
  421                         am->am_waiters++;
  422                         error = mtx_sleep(am, &am->am_lock, PCATCH,
  423                             "acmtx", tmo);
  424                         am->am_waiters--;
  425                         if (error == EINTR || am->am_reset) {
  426                                 status = AE_ERROR;
  427                                 break;
  428                         }
  429                         if (ACPIMTX_AVAIL(am))
  430                                 break;
  431                         slptick = ticks - prevtick;
  432                         if (slptick >= tmo || slptick < 0) {
  433                                 status = AE_TIME;
  434                                 break;
  435                         }
  436                         tmo -= slptick;
  437                 }
  438         }
  439         if (ACPI_SUCCESS(status))
  440                 am->am_owner = curthread;
  441 
  442         mtx_unlock(&am->am_lock);
  443 
  444         return_ACPI_STATUS (status);
  445 }
  446 
  447 void
  448 AcpiOsReleaseMutex(ACPI_MUTEX Handle)
  449 {
  450         struct acpi_mutex       *am = (struct acpi_mutex *)Handle;
  451 
  452         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  453 
  454         if (am == NULL) {
  455                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  456                     "cannot release null mutex\n"));
  457                 return_VOID;
  458         }
  459 
  460         mtx_lock(&am->am_lock);
  461 
  462         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "release %s\n", am->am_name));
  463 
  464         if (ACPIMTX_OWNED(am)) {
  465                 if (am->am_nested > 0) {
  466                         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  467                             "release nested %s, depth %d\n",
  468                             am->am_name, am->am_nested));
  469                         am->am_nested--;
  470                 } else
  471                         am->am_owner = NULL;
  472         } else {
  473                 if (ACPIMTX_AVAIL(am))
  474                         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  475                             "release already available %s\n", am->am_name));
  476                 else
  477                         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  478                             "release unowned %s from %p, depth %d\n",
  479                             am->am_name, am->am_owner, am->am_nested));
  480         }
  481         if (am->am_waiters > 0 && ACPIMTX_AVAIL(am))
  482                 wakeup_one(am);
  483 
  484         mtx_unlock(&am->am_lock);
  485 }
  486 
  487 #undef ACPIMTX_AVAIL
  488 #undef ACPIMTX_OWNED
  489 
  490 /*
  491  * ACPI_SPINLOCK
  492  */
  493 struct acpi_spinlock {
  494         struct mtx      al_lock;
  495         char            al_name[32];
  496         int             al_nested;
  497 };
  498 
  499 ACPI_STATUS
  500 AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle)
  501 {
  502         struct acpi_spinlock    *al;
  503 
  504         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  505 
  506         if (OutHandle == NULL)
  507                 return_ACPI_STATUS (AE_BAD_PARAMETER);
  508 
  509         if ((al = malloc(sizeof(*al), M_ACPISEM, M_NOWAIT | M_ZERO)) == NULL)
  510                 return_ACPI_STATUS (AE_NO_MEMORY);
  511 
  512 #ifdef ACPI_DEBUG
  513         if (OutHandle == &AcpiGbl_GpeLock)
  514                 snprintf(al->al_name, sizeof(al->al_name), "ACPI lock (GPE)");
  515         else if (OutHandle == &AcpiGbl_HardwareLock)
  516                 snprintf(al->al_name, sizeof(al->al_name), "ACPI lock (HW)");
  517         else
  518 #endif
  519         snprintf(al->al_name, sizeof(al->al_name), "ACPI lock (%p)", al);
  520         mtx_init(&al->al_lock, al->al_name, NULL, MTX_SPIN);
  521 
  522         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "created %s\n", al->al_name));
  523 
  524         *OutHandle = (ACPI_SPINLOCK)al;
  525 
  526         return_ACPI_STATUS (AE_OK);
  527 }
  528 
  529 void
  530 AcpiOsDeleteLock(ACPI_SPINLOCK Handle)
  531 {
  532         struct acpi_spinlock    *al = (struct acpi_spinlock *)Handle;
  533 
  534         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  535 
  536         if (al == NULL) {
  537                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  538                     "cannot delete null spinlock\n"));
  539                 return_VOID;
  540         }
  541 
  542         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "delete %s\n", al->al_name));
  543 
  544         mtx_destroy(&al->al_lock);
  545         free(al, M_ACPISEM);
  546 }
  547 
  548 ACPI_CPU_FLAGS
  549 AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
  550 {
  551         struct acpi_spinlock    *al = (struct acpi_spinlock *)Handle;
  552 
  553         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  554 
  555         if (al == NULL) {
  556                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  557                     "cannot acquire null spinlock\n"));
  558                 return (0);
  559         }
  560 
  561         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "acquire %s\n", al->al_name));
  562 
  563         if (mtx_owned(&al->al_lock)) {
  564                 al->al_nested++;
  565                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  566                     "acquire nested %s, depth %d\n",
  567                     al->al_name, al->al_nested));
  568         } else
  569                 mtx_lock_spin(&al->al_lock);
  570 
  571         return (0);
  572 }
  573 
  574 void
  575 AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
  576 {
  577         struct acpi_spinlock    *al = (struct acpi_spinlock *)Handle;
  578 
  579         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  580 
  581         if (al == NULL) {
  582                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  583                     "cannot release null spinlock\n"));
  584                 return_VOID;
  585         }
  586 
  587         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "release %s\n", al->al_name));
  588 
  589         if (mtx_owned(&al->al_lock)) {
  590                 if (al->al_nested > 0) {
  591                         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  592                             "release nested %s, depth %d\n",
  593                             al->al_name, al->al_nested));
  594                         al->al_nested--;
  595                 } else
  596                         mtx_unlock_spin(&al->al_lock);
  597         } else
  598                 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
  599                     "cannot release unowned %s\n", al->al_name));
  600 }
  601 
  602 /* Section 5.2.10.1: global lock acquire/release functions */
  603 
  604 /*
  605  * Acquire the global lock.  If busy, set the pending bit.  The caller
  606  * will wait for notification from the BIOS that the lock is available
  607  * and then attempt to acquire it again.
  608  */
  609 int
  610 acpi_acquire_global_lock(volatile uint32_t *lock)
  611 {
  612         uint32_t        new, old;
  613 
  614         do {
  615                 old = *lock;
  616                 new = (old & ~ACPI_GLOCK_PENDING) | ACPI_GLOCK_OWNED;
  617                 if ((old & ACPI_GLOCK_OWNED) != 0)
  618                         new |= ACPI_GLOCK_PENDING;
  619         } while (atomic_cmpset_32(lock, old, new) == 0);
  620 
  621         return ((new & ACPI_GLOCK_PENDING) == 0);
  622 }
  623 
  624 /*
  625  * Release the global lock, returning whether there is a waiter pending.
  626  * If the BIOS set the pending bit, OSPM must notify the BIOS when it
  627  * releases the lock.
  628  */
  629 int
  630 acpi_release_global_lock(volatile uint32_t *lock)
  631 {
  632         uint32_t        new, old;
  633 
  634         do {
  635                 old = *lock;
  636                 new = old & ~(ACPI_GLOCK_PENDING | ACPI_GLOCK_OWNED);
  637         } while (atomic_cmpset_32(lock, old, new) == 0);
  638 
  639         return ((old & ACPI_GLOCK_PENDING) != 0);
  640 }

Cache object: 8b0c9b5bf75e7aea610be012aba01d27


[ 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.