Commit 39ca8a68 authored by Adam Wujek's avatar Adam Wujek

Merge branch 'adam-shmem'

Uplift shmem from wr-switch-sw repo.
Fix previous uplift of shmem and improve debug printout.
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parents 1edcf5c4 669743b9
......@@ -61,19 +61,21 @@ void wrs_shm_set_path(char *new_path);
void wrs_shm_ignore_flag_locked(int ignore_flag);
/* get vs. put, like in the kernel. Errors are in errno (see source) */
void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags);
int wrs_shm_put(void *headptr);
struct wrs_shm_head *wrs_shm_get(enum wrs_shm_name name_id, char *name,
unsigned long flags);
int wrs_shm_put(struct wrs_shm_head *head);
/* A reader may wait for the writer (polling on version field) */
void wrs_shm_wait(void *headptr, int msec_step, int retries, FILE *msg);
void wrs_shm_wait(struct wrs_shm_head *head, int msec_step, int retries,
FILE *msg);
int wrs_shm_get_and_check(enum wrs_shm_name shm_name,
struct wrs_shm_head **head);
/* The writer can allocate structures that live in the area itself */
void *wrs_shm_alloc(void *headptr, size_t size);
void *wrs_shm_alloc(struct wrs_shm_head *head, size_t size);
/* The reader can track writer's pointers, if they are in the area */
void *wrs_shm_follow(void *headptr, void *ptr);
void *wrs_shm_follow(struct wrs_shm_head *head, void *ptr);
/* Before and after writing a chunk of data, act on sequence and stamp */
#define WRS_SHM_WRITE_BEGIN 1
......@@ -82,16 +84,17 @@ void *wrs_shm_follow(void *headptr, void *ptr);
/* A helper to pass the name of caller function */
#define wrs_shm_write(headptr, flags) wrs_shm_write_caller(headptr, flags, \
__func__)
extern void wrs_shm_write_caller(void *headptr, int flags, const char *caller);
extern void wrs_shm_write_caller(struct wrs_shm_head *head, int flags,
const char *caller);
/* A reader can rely on the sequence number (in the <linux/seqlock.h> way) */
extern unsigned wrs_shm_seqbegin(void *headptr);
extern int wrs_shm_seqretry(void *headptr, unsigned start);
extern unsigned wrs_shm_seqbegin(struct wrs_shm_head *head);
extern int wrs_shm_seqretry(struct wrs_shm_head *head, unsigned start);
/* A reader can check wether information is current enough */
extern int wrs_shm_age(void *headptr);
extern int wrs_shm_age(struct wrs_shm_head *head);
/* A reader can get the information pointer, for a specific version, or NULL */
extern void *wrs_shm_data(void *headptr, unsigned version);
extern void *wrs_shm_data(struct wrs_shm_head *head, unsigned version);
#endif /* __WRS_SHM_H__ */
......@@ -39,7 +39,8 @@ void wrs_shm_ignore_flag_locked(int ignore_flag)
/* Get wrs shared memory */
/* return NULL and set errno on error */
void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags)
struct wrs_shm_head *wrs_shm_get(enum wrs_shm_name name_id, char *name,
unsigned long flags)
{
struct wrs_shm_head *head;
struct stat stbuf;
......@@ -120,20 +121,19 @@ void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags)
head->pidsequence++;
/* version and size are up to the user (or to allocation) */
return map;
return (struct wrs_shm_head *) map;
}
/* Put wrs shared memory */
/* return 0 on success, !0 on error */
int wrs_shm_put(void *headptr)
int wrs_shm_put(struct wrs_shm_head *head)
{
struct wrs_shm_head *head = headptr;
int err;
if (head->pid == getpid()) {
head->pid = 0; /* mark that we are not writers any more */
close(head->fd);
}
if ((err = munmap(headptr, WRS_SHM_MAX_SIZE)) < 0)
if ((err = munmap(head, WRS_SHM_MAX_SIZE)) < 0)
return err;
return 0;
}
......@@ -175,9 +175,9 @@ int wrs_shm_get_and_check(enum wrs_shm_name shm_name,
}
/* The writer can allocate structures that live in the area itself */
void *wrs_shm_alloc(void *headptr, size_t size)
void *wrs_shm_alloc(struct wrs_shm_head *head, size_t size)
{
struct wrs_shm_head *head = headptr;
void *headptr = (void *) head;
void *nextptr;
if (head->pid != getpid())
......@@ -196,73 +196,77 @@ void *wrs_shm_alloc(void *headptr, size_t size)
}
/* The reader can track writer's pointers, if they are in the area */
void *wrs_shm_follow(void *headptr, void *ptr)
void *wrs_shm_follow(struct wrs_shm_head *head, void *ptr)
{
struct wrs_shm_head *head = headptr;
void *headptr = (void *) head;
if (ptr < head->mapbase || ptr > head->mapbase + WRS_SHM_MAX_SIZE)
return NULL; /* not in the area */
return headptr + (ptr - head->mapbase);
}
/* Before and after writing a chunk of data, act on sequence and stamp */
void wrs_shm_write_caller(void *headptr, int flags, const char *caller)
void wrs_shm_write_caller(struct wrs_shm_head *head, int flags,
const char *caller)
{
struct wrs_shm_head *head = headptr;
char *msg = "Wrong parameter";
head->sequence++;
pr_debug("caller: %s\n", caller);
if (flags == WRS_SHM_WRITE_BEGIN) {
msg = "write begin";
}
if (flags == WRS_SHM_WRITE_END) {
msg = "write end";
}
pr_debug("caller of a function wrs_shm_write is %s, called for \"%s\" "
"with the flag \"%s\"\n", caller, head->name, msg);
head->sequence += 2;
if (flags == WRS_SHM_WRITE_BEGIN) {
if (head->sequence & WRS_SHM_LOCK_MASK)
pr_error("Trying to lock already locked shmem on the "
"write end! Sequence number is %d. The caller"
" of wrs_shm_write is %s\n",
head->sequence, caller);
head->sequence |= WRS_SHM_LOCK_MASK;
}
if (flags == WRS_SHM_WRITE_END) {
/* At end-of-writing update the timestamp too */
head->stamp = get_monotonic_sec();
if (head->sequence & 1)
pr_error("On the shmem write end the sequence number "
"(%d) is even (should be odd). The caller of"
" wrs_shm_write is %s\n",
head->sequence, caller);
} else {
if (!(head->sequence & 1))
pr_error("On the shmem write begin the sequence number"
" (%d) is odd (should be even). The caller of"
" wrs_shm_write is %s\n",
head->sequence, caller);
if (!(head->sequence & WRS_SHM_LOCK_MASK))
pr_error("Trying to unlock already unlocked shmem on "
"the write begin! Sequence number is %d. The "
"caller of wrs_shm_write is %s\n",
head->sequence, caller);
head->sequence &= ~WRS_SHM_LOCK_MASK;
}
return;
}
/* A reader can rely on the sequence number (in the <linux/seqlock.h> way) */
unsigned wrs_shm_seqbegin(void *headptr)
unsigned wrs_shm_seqbegin(struct wrs_shm_head *head)
{
struct wrs_shm_head *head = headptr;
return head->sequence;
}
int wrs_shm_seqretry(void *headptr, unsigned start)
int wrs_shm_seqretry(struct wrs_shm_head *head, unsigned start)
{
struct wrs_shm_head *head = headptr;
if (start & 1)
if (start & WRS_SHM_LOCK_MASK)
return 1; /* it was odd: retry */
return head->sequence != start;
}
/* A reader can check wether information is current enough */
int wrs_shm_age(void *headptr)
int wrs_shm_age(struct wrs_shm_head *head)
{
struct wrs_shm_head *head = headptr;
return get_monotonic_sec() - head->stamp;
}
/* A reader can get the information pointer, for a specific version, or NULL */
void *wrs_shm_data(void *headptr, unsigned version)
void *wrs_shm_data(struct wrs_shm_head *head, unsigned version)
{
struct wrs_shm_head *head = headptr;
void *headptr = (void *) head;
if (head->version != version)
return NULL;
......
......@@ -59,7 +59,7 @@ struct wrs_shm_head *ppsi_head;
* we need to call calloc, to reset all stuff that used to be static,
* but we'd better have a simple prototype, compatilble with wrs_shm_alloc()
*/
static void *local_malloc(void *headptr, size_t size)
static void *local_malloc(struct wrs_shm_head *headptr, size_t size)
{
void *retval = malloc(size);
......@@ -78,7 +78,8 @@ int main(int argc, char **argv)
int i, hal_retries;
struct wrs_shm_head *hal_head;
struct hal_shmem_header *h;
void *(*alloc_fn)(void *headptr, size_t size) = local_malloc;
void *(*alloc_fn)(struct wrs_shm_head *headptr, size_t size);
alloc_fn = local_malloc;
setbuf(stdout, NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment