diff options
Diffstat (limited to 'src/platform_libs.c')
-rw-r--r-- | src/platform_libs.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/platform_libs.c b/src/platform_libs.c new file mode 100644 index 0000000..4cd576b --- /dev/null +++ b/src/platform_libs.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define FARF_ERROR 1 +#include "HAP_farf.h" +#include "platform_libs.h" +#include "AEEatomic.h" +#include "AEEstd.h" +#include "AEEStdErr.h" +#include <stdio.h> +#include <assert.h> +#include "verify.h" + +extern struct platform_lib* (*pl_list[])(void); +static uint32 atomic_IfNotThenAdd(uint32* volatile puDest, uint32 uCompare, int nAdd); + +int pl_lib_init(struct platform_lib* (*plf)(void)) { + int nErr = AEE_SUCCESS; + struct platform_lib* pl = plf(); + if(1 == atomic_Add(&pl->uRefs, 1)) { + if(pl->init) { + FARF(HIGH, "calling init for %s",pl->name); + nErr = pl->init(); + FARF(HIGH, "init for %s returned %x",pl->name, nErr); + } + pl->nErr = nErr; + } + if(pl->nErr != AEE_SUCCESS) { + VERIFY_EPRINTF("Error %x: %s init failed", nErr, pl->name); + } + return pl->nErr; +} + +void pl_lib_deinit(struct platform_lib* (*plf)(void)) { + struct platform_lib* pl = plf(); + if(1 == atomic_IfNotThenAdd(&pl->uRefs, 0, -1)) { + if(pl->deinit && pl->nErr == 0) { + pl->deinit(); + } + } + return; +} + +static int pl_init_lst(struct platform_lib* (*lst[])(void)) { + int nErr = AEE_SUCCESS; + int ii; + for(ii = 0; lst[ii] != 0; ++ii) { + nErr = pl_lib_init(lst[ii]); + if(nErr != 0) { + break; + } + } + if(nErr != AEE_SUCCESS) { + VERIFY_EPRINTF("Error %x: plinit failed\n", nErr); + } + return nErr; + +} +int pl_init(void) { + int nErr = pl_init_lst(pl_list); + return nErr; +} + +static void pl_deinit_lst(struct platform_lib* (*lst[])(void)) { + int size, ii; + for(size = 0; lst[size] != 0; ++size) {;} + for(ii = size - 1; ii >= 0; --ii) { + pl_lib_deinit(lst[ii]); + } + return; +} + + +void pl_deinit(void) { + pl_deinit_lst(pl_list); + return; +} + +static uint32 atomic_IfNotThenAdd(uint32* volatile puDest, uint32 uCompare, int nAdd) +{ + uint32 uPrev; + uint32 uCurr; + do { + //check puDest + uCurr = *puDest; + uPrev = uCurr; + //see if we need to update it + if(uCurr != uCompare) { + //update it + uPrev = atomic_CompareAndExchange(puDest, uCurr + nAdd, uCurr); + } + //verify that the value was the same during the update as when we decided to update + } while(uCurr != uPrev); + return uPrev; +} + |