/
UCS
/
snoopy
Обзор
Документация
Войти
/
UCS
/
snoopy
Код
Запросы
0
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/tsrm.c
423 строки
10 KB
Bostjan Skufca Jese
Change full name from "Snoopy Logger" to "Snoopy Command Logger"
27 авг 2022, 05:11
27 авг 2022, 05:11
a01a468
Код
Авторство
О чём код?
/* * SNOOPY COMMAND LOGGER * * File: tsrm.c * * Copyright (c) 2015 Bostjan Skufca <bostjan@a2o.si> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Includes order: from local to global */ #include "snoopy.h" #include "tsrm.h" #include "configuration.h" #include "inputdatastorage.h" #include "util/list-snoopy.h" #include <pthread.h> #include <stdlib.h> /* * Global variables */ pthread_once_t snoopy_tsrm_init_onceControl = PTHREAD_ONCE_INIT; pthread_mutex_t snoopy_tsrm_threadRepo_mutex; pthread_mutexattr_t snoopy_tsrm_threadRepo_mutexAttr; list_t snoopy_tsrm_threadRepo_data = { .first = NULL, .last = NULL, .count = 0, }; list_t *snoopy_tsrm_threadRepo = &snoopy_tsrm_threadRepo_data; /* * Non-exported function prototypes */ void snoopy_tsrm_init (); int snoopy_tsrm_doesThreadRepoEntryExist (snoopy_tsrm_threadId_t threadId, int mutex_already_locked); snoopy_tsrm_threadId_t snoopy_tsrm_getCurrentThreadId (); listNode_t* snoopy_tsrm_getCurrentThreadRepoEntry (); snoopy_tsrm_threadData_t* snoopy_tsrm_getCurrentThreadData (); snoopy_tsrm_threadData_t* snoopy_tsrm_createNewThreadData (snoopy_tsrm_threadId_t threadId); /* * snoopy_tsrm_ctor * * Description: * Initialize threadRepo list. * * Params: * (none) * * Return: * void */ void snoopy_tsrm_ctor () { snoopy_tsrm_threadId_t curTid; snoopy_tsrm_threadData_t *tData; // Initialize threading support pthread_once(&snoopy_tsrm_init_onceControl, &snoopy_tsrm_init); // Get my thread id - before mutex, no need for mutex here curTid = snoopy_tsrm_getCurrentThreadId(); // Mutex START pthread_mutex_lock(&snoopy_tsrm_threadRepo_mutex); // Create my entry if it does not exist if (SNOOPY_FALSE == snoopy_tsrm_doesThreadRepoEntryExist(curTid, SNOOPY_TRUE)) { tData = snoopy_tsrm_createNewThreadData(curTid); snoopy_util_list_push(snoopy_tsrm_threadRepo, tData); } // Mutex END pthread_mutex_unlock(&snoopy_tsrm_threadRepo_mutex); } /* * snoopy_tsrm_dtor * * Description: * Removes own entry from threadRepo, or removes threadRepo altogether. * * Params: * (none) * * Return: * void */ void snoopy_tsrm_dtor () { listNode_t *tRepoEntry; snoopy_tsrm_threadData_t *tData; // Get my thread data structure tRepoEntry = snoopy_tsrm_getCurrentThreadRepoEntry(); if (NULL == tRepoEntry) { // This is an error condition, but let's not free NULLs below return; } // Mutex START pthread_mutex_lock(&snoopy_tsrm_threadRepo_mutex); // Remove from repo tData = snoopy_util_list_remove(snoopy_tsrm_threadRepo, tRepoEntry); // Mutex END pthread_mutex_unlock(&snoopy_tsrm_threadRepo_mutex); // Free the results AFTER my node has been removed from repo free(tData->inputdatastorage); free(tData->configuration); free(tData); return; } /* * snoopy_tsrm_init * * Description: * Initialize threading subsystem. This function should be run * only once, by only one thread. * * Params: * (none) * * Return: * void */ void snoopy_tsrm_init () { // Initialize threadRepo mutex pthread_mutexattr_init (&snoopy_tsrm_threadRepo_mutexAttr); pthread_mutexattr_settype(&snoopy_tsrm_threadRepo_mutexAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init (&snoopy_tsrm_threadRepo_mutex, &snoopy_tsrm_threadRepo_mutexAttr); } /* * snoopy_tsrm_doesThreadRepoEntryExist * * Description: * Check if thread with id threadId already has an entry in Snoopy's thread * repository. * * Params: * snoopy_tsrm_threadId_t: Thread ID to look for * * Return: * int: SNOOPY_TRUE if yes, SNOOPY_FALSE if not */ int snoopy_tsrm_doesThreadRepoEntryExist (snoopy_tsrm_threadId_t threadId, int mutex_already_locked) { const snoopy_tsrm_threadData_t *tData; int retVal = SNOOPY_FALSE; // Mutex START if (SNOOPY_TRUE != mutex_already_locked) { pthread_mutex_lock(&snoopy_tsrm_threadRepo_mutex); } listNode_t * curNode = NULL; while (NULL != (curNode = snoopy_util_list_fetchNextNode(snoopy_tsrm_threadRepo, curNode))) { if (NULL == curNode->value) { continue; } tData = curNode->value; if (0 != pthread_equal(threadId, tData->threadId)) { /* Thread ID matches */ retVal = SNOOPY_TRUE; goto FOUND; } } FOUND: // Mutex END if (SNOOPY_TRUE != mutex_already_locked) { pthread_mutex_unlock(&snoopy_tsrm_threadRepo_mutex); } return retVal; } /* * snoopy_tsrm_createNewThreadData * * Description: * Mallocs space and creates new thread data structure, for given thread ID. * * Params: * snoopy_tsrm_threadId_t: Thread ID to create entry for * * Return: * snoopy_tsrm_threadData_t*: Pointer to newly-created threadData structure */ snoopy_tsrm_threadData_t* snoopy_tsrm_createNewThreadData (snoopy_tsrm_threadId_t threadId) { snoopy_tsrm_threadData_t *tData; // Allocte storage memory for new threadData structure tData = malloc(sizeof(snoopy_tsrm_threadData_t)); tData->configuration = malloc(sizeof(snoopy_configuration_t)); tData->inputdatastorage = malloc(sizeof(snoopy_inputdatastorage_t)); // Store thread ID tData->threadId = threadId; // Initialize empty values snoopy_configuration_setUninitialized (tData->configuration); snoopy_inputdatastorage_setUninitialized(tData->inputdatastorage); return tData; } /* * snoopy_tsrm_getCurrentThreadId * * Description: * Retrieve id of current thread * * Params: * (none) * * Return: * snoopy_tsrm_threadId_t: Current thread id */ snoopy_tsrm_threadId_t snoopy_tsrm_getCurrentThreadId () { return pthread_self(); } /* * snoopy_tsrm_getCurrentThreadRepoEntry * * Description: * Retrieve pointer to threadRepo list node structure of current thread. * * Params: * (none) * * Return: * listNode_t*: Current threadRepo entry, or null if it does not exist */ listNode_t * snoopy_tsrm_getCurrentThreadRepoEntry () { snoopy_tsrm_threadId_t myThreadId; listNode_t *tRepoEntry = NULL; const snoopy_tsrm_threadData_t *tData; // This is the thread ID we are looking for myThreadId = snoopy_tsrm_getCurrentThreadId(); // Mutex START pthread_mutex_lock(&snoopy_tsrm_threadRepo_mutex); listNode_t * curNode = NULL; while (NULL != (curNode = snoopy_util_list_fetchNextNode(snoopy_tsrm_threadRepo, curNode))) { // This should not happen, but maybe, just maybe, there is another thread // that is just creating a new entry. if (NULL == curNode->value) { continue; } tData = curNode->value; if (0 != pthread_equal(myThreadId, tData->threadId)) { tRepoEntry = curNode; goto FOUND; } } FOUND: // Mutex END pthread_mutex_unlock(&snoopy_tsrm_threadRepo_mutex); // Return return tRepoEntry; } /* * snoopy_tsrm_getCurrentThreadData * * Description: * Retrieve pointer to thread data structure of current thread. Creates * a new repo entry if it does not exist. * * Params: * (none) * * Return: * snoopy_tsrm_threadData_t: Current threadRepo list entry, or NULL */ snoopy_tsrm_threadData_t* snoopy_tsrm_getCurrentThreadData () { listNode_t *tRepoEntry; tRepoEntry = snoopy_tsrm_getCurrentThreadRepoEntry(); if (NULL == tRepoEntry) { return NULL; } return tRepoEntry->value; } /* * snoopy_tsrm_get_configuration() * * Description: * Retrieve configuration array pointer for current thread. * This function is to be consumed by the rest of Snoopy. * * Params: * (none) * * Return: * snoopy_configuration_t*: Pointer to thread-specific Snoopy configuration data structure */ snoopy_configuration_t* snoopy_tsrm_get_configuration () { snoopy_tsrm_threadData_t *tData; tData = snoopy_tsrm_getCurrentThreadData(); return tData->configuration; } /* * snoopy_tsrm_get_inputdatastorage() * * Description: * Retrieve input data storage array pointer for current thread. * This function is to be consumed by the rest of Snoopy. * * Params: * (none) * * Return: * snoopy_inputdatastorage_t*: Pointer to thread-specific input data storage structure */ snoopy_inputdatastorage_t* snoopy_tsrm_get_inputdatastorage () { snoopy_tsrm_threadData_t *tData; tData = snoopy_tsrm_getCurrentThreadData(); return tData->inputdatastorage; } /* * snoopy_tsrm_get_threadCount() * * Description: * Retrieves number of currently configured threads. * * Params: * (none) * * Return: * snoopy_inputdatastorage_t*: Pointer to thread-specific input data storage structure */ int snoopy_tsrm_get_threadCount () { int threadCount; // Mutex START pthread_mutex_lock(&snoopy_tsrm_threadRepo_mutex); // Get count threadCount = snoopy_tsrm_threadRepo->count; // Mutex END pthread_mutex_unlock(&snoopy_tsrm_threadRepo_mutex); return threadCount; }