diff options
Diffstat (limited to 'src/icastats_shared.c')
-rw-r--r-- | src/icastats_shared.c | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/src/icastats_shared.c b/src/icastats_shared.c new file mode 100644 index 0000000..3fa29d3 --- /dev/null +++ b/src/icastats_shared.c @@ -0,0 +1,314 @@ +/* This program is released under the Common Public License V1.0 + * + * You should have received a copy of Common Public License V1.0 along with + * with this program. + */ + +/** + * Authors: Christian Maaser <cmaaser@de.ibm.com> + * Holger Dengler <hd@linux.vnet.ibm.com> + * Benedikt Klotz <benedikt.klotz@de.ibm.com> + * + * Copyright IBM Corp. 2009, 2011, 2013 + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <pwd.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <fcntl.h> +#include <dirent.h> +#include "icastats.h" + +#define NOT_INITIALIZED (-1) +#define NAME_LENGHT 20 + +static stats_entry_t *stats = NULL; +volatile int stats_shm_handle = NOT_INITIALIZED; + + + +static void atomic_add(int *x, int i) +{ + int old; + int new; + asm volatile (" l %0,%2\n" + "0: lr %1,%0\n" + " ar %1,%3\n" + " cs %0,%1,%2\n" + " jl 0b" + :"=&d" (old), "=&d"(new), "=Q"(*x) + :"d"(i), "Q"(*x) + :"cc", "memory"); +} + + +/* open shared memory segment + * Arguments: + * @user: if user is -1 stats_mmap will open the shared memory segent of the same + * user. + * If it is not -1, stats_mmap will treat it as uid and will open the shared memory + * segment of this userid + * return value: + * 0 - Success + * -1 - Error: See errno for errorcode + */ + +int stats_mmap(int user) +{ + if (stats == NULL) { + char shm_id[NAME_LENGHT]; + sprintf(shm_id, "icastats_%d", user == -1? geteuid(): user); + + stats_shm_handle = shm_open(shm_id, O_CREAT | O_RDWR, + S_IRUSR | S_IWUSR); + + if (stats_shm_handle == NOT_INITIALIZED) + return -1; + if (ftruncate(stats_shm_handle, STATS_SHM_SIZE) == -1) + return -1; + + stats = (stats_entry_t *) mmap(NULL, STATS_SHM_SIZE, PROT_READ | + PROT_WRITE, MAP_SHARED, + stats_shm_handle, 0); + if (stats == MAP_FAILED){ + close(stats_shm_handle); + stats = NULL; + return -1; + } + } + return 0; +} + +/* Close and/or delete the shared memory segment + * Argument: + * @unlink - if unlink is true the shared memory segment will be + * deleted. If it is false it will only be closed. + */ + +void stats_munmap(int unlink) +{ + char shm_id[NAME_LENGHT]; + sprintf(shm_id, "icastats_%d", geteuid()); + + if (stats == NULL) + return; + + munmap(stats, STATS_SHM_SIZE); + close(stats_shm_handle); + stats_shm_handle = NOT_INITIALIZED; + + if(unlink == SHM_DESTROY) + shm_unlink(shm_id); + stats = NULL; +} + +/* query the shared memory segment for a specific field + * arguments: + * @field - the enum of the field see icastats.h + * @hardware - valid values are ALGO_SW for software statistics + * and ALGO_HW for hardware statistics + * @direction - valid values are ENCRYPT and DECRYPT + */ + +uint32_t stats_query(stats_fields_t field, int hardware, int direction) +{ + if (stats == NULL) + return 0; + + if (direction == ENCRYPT) + if (hardware == ALGO_HW) + return stats[field].enc.hw; + else + return stats[field].enc.sw; + else + if (hardware == ALGO_HW) + return stats[field].dec.hw; + else + return stats[field].dec.sw; +} + +/* Returns the statistic data in a stats_entry_t array + * @entries - Needs to be a array of size ICA_NUM_STATS. + */ + +void get_stats_data(stats_entry_t *entries) +{ + unsigned int i; + for(i = 0;i<ICA_NUM_STATS; i++){ + entries[i].enc.hw = stats_query(i, ALGO_HW, ENCRYPT); + entries[i].enc.sw = stats_query(i, ALGO_SW, ENCRYPT); + entries[i].dec.hw = stats_query(i, ALGO_HW, DECRYPT); + entries[i].dec.sw = stats_query(i, ALGO_SW, DECRYPT); + } +} + + + +/* get the statistic data from all shared memory segments + * accumulated in one variable + * @sum: sum must be array of the size of ICA_NUM_STATS + * After a call to this function sum contains the accumulated + * data of all shared memory segments. + * Return value: + * 1 - Success + * 0 - Error, check errno! + */ + +int get_stats_sum(stats_entry_t *sum) +{ + unsigned int i; + struct dirent *direntp; + DIR *shmDir; + + memset(sum, 0, sizeof(stats_entry_t)*ICA_NUM_STATS); + if((shmDir = opendir("/dev/shm")) == NULL) + return 0; + + while((direntp = readdir(shmDir)) != NULL){ + if(strstr(direntp->d_name, "icastats_") != NULL){ + int fd; + stats_entry_t *tmp; + + if((getpwuid(atoi(&direntp->d_name[9]))) == NULL){ + closedir(shmDir); + return 0; + } + + if ((fd = shm_open(direntp->d_name, O_RDONLY, 0)) == -1){ + closedir(shmDir); + return 0; + } + if ((tmp = (stats_entry_t *)mmap(NULL, STATS_SHM_SIZE, + PROT_READ, MAP_SHARED, + fd, 0)) == MAP_FAILED){ + closedir(shmDir); + close(fd); + return 0; + } + + for(i = 0; i<ICA_NUM_STATS; ++i){ + sum[i].enc.hw += tmp[i].enc.hw; + sum[i].enc.sw += tmp[i].enc.sw; + sum[i].dec.hw += tmp[i].dec.hw; + sum[i].dec.sw += tmp[i].dec.sw; + } + munmap(tmp, STATS_SHM_SIZE); + close(fd); + } + } + closedir(shmDir); + return 1; +} + +/* Open the shared memory segment of the next user! + * Each call to this function will open one file of the + * /dev/shm directory. The function will return NULL when all files + * in the directory were opened. + * WARNING: You should never call this function only one time! Call this funtion in a loop with + * abort condition unequal NULL. + * The directory will reamin open if you don't wait for NULL! + * Return value: + * the name of the next user! + * It is NULL when all files were opened. + */ + +char *get_next_usr() +{ + struct dirent *direntp; + static DIR *shmDir = NULL; + + /* Closes shm and set stats NULL */ + stats_munmap(SHM_CLOSE); + + if(shmDir == NULL){ + if((shmDir = opendir("/dev/shm")) == NULL) + return NULL; + } + while((direntp = readdir(shmDir)) != NULL){ + if(strstr(direntp->d_name, "icastats_") != NULL){ + int uid = atoi(&direntp->d_name[9]); + struct passwd *pwd; + if((pwd = getpwuid(uid)) == NULL) + return NULL; + if(stats_mmap(uid) == -1) + return NULL; + + return pwd->pw_name; + } else{ + continue; + } + } + closedir(shmDir); + shmDir = NULL; + return NULL; +} + +/* increments a field of the shared memory segment + * arguments: + * @field - the enum of the field see icastats.h + * @hardware - valid values are ALGO_SW for software statistics + * and ALGO_HW for hardware statistics + * @direction - valid values are ENCRYPT and DECRYPT + */ + + +void stats_increment(stats_fields_t field, int hardware, int direction) +{ + if (stats == NULL) + return; + + if(direction == ENCRYPT) + if (hardware == ALGO_HW) + atomic_add((int *)&stats[field].enc.hw, 1); + else + atomic_add((int *)&stats[field].enc.sw, 1); + else + if (hardware == ALGO_HW) + atomic_add((int *)&stats[field].dec.hw, 1); + else + atomic_add((int *)&stats[field].dec.sw, 1); +} + + +/* Reset the shared memory segment to zero + */ +void stats_reset() +{ + if (stats == NULL) + return; + + memset(stats, 0, sizeof(stats_entry_t)*ICA_NUM_STATS); +} + + +/* Delete all shared memory segments + * Return values: + * 1 - Success + * 0 - Error, check errno! + */ + +int delete_all() +{ + stats_munmap(SHM_DESTROY); + struct dirent *direntp; + DIR *shmDir; + if((shmDir = opendir("/dev/shm")) == NULL) + return 0; + + while((direntp = readdir(shmDir)) != NULL){ + if(strstr(direntp->d_name, "icastats_") != NULL){ + if(shm_unlink(direntp->d_name) == -1) + return 0; + } + } + closedir(shmDir); + return 1; +} + |