2012-09-03 09:14:36 +00:00
|
|
|
/*
|
|
|
|
* shctx.h - shared context management functions for SSL
|
|
|
|
*
|
|
|
|
* Copyright (C) 2011-2012 EXCELIANCE
|
|
|
|
*
|
|
|
|
* Author: Emeric Brun - emeric@exceliance.fr
|
|
|
|
*
|
|
|
|
* 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 of the License, or (at your option) any later version.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SHCTX_H
|
|
|
|
#define SHCTX_H
|
2017-10-09 12:17:39 +00:00
|
|
|
|
2020-05-27 16:01:47 +00:00
|
|
|
#include <haproxy/list.h>
|
2017-10-09 12:17:39 +00:00
|
|
|
#include <types/shctx.h>
|
|
|
|
|
2019-03-29 16:26:33 +00:00
|
|
|
#include <inttypes.h>
|
2012-09-03 09:14:36 +00:00
|
|
|
|
2017-10-09 12:17:39 +00:00
|
|
|
#ifndef USE_PRIVATE_CACHE
|
|
|
|
#ifdef USE_PTHREAD_PSHARED
|
|
|
|
#include <pthread.h>
|
|
|
|
#else
|
|
|
|
#ifdef USE_SYSCALL_FUTEX
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <linux/futex.h>
|
|
|
|
#include <sys/syscall.h>
|
2012-09-03 09:14:36 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
2012-11-26 17:37:12 +00:00
|
|
|
#endif
|
|
|
|
|
2018-10-22 14:21:39 +00:00
|
|
|
int shctx_init(struct shared_context **orig_shctx,
|
2018-10-25 18:31:40 +00:00
|
|
|
int maxblocks, int blocksize, unsigned int maxobjsz,
|
|
|
|
int extra, int shared);
|
2018-10-22 15:55:57 +00:00
|
|
|
struct shared_block *shctx_row_reserve_hot(struct shared_context *shctx,
|
|
|
|
struct shared_block *last, int data_len);
|
MEDIUM: shctx: separate ssl and shctx
This patch reorganize the shctx API in a generic storage API, separating
the shared SSL session handling from its core.
The shctx API only handles the generic data part, it does not know what
kind of data you use with it.
A shared_context is a storage structure allocated in a shared memory,
allowing its usage in a multithread or a multiprocess context.
The structure use 2 linked list, one containing the available blocks,
and another for the hot locked blocks. At initialization the available
list is filled with <maxblocks> blocks of size <blocksize>. An <extra>
space is initialized outside the list in case you need some specific
storage.
+-----------------------+--------+--------+--------+--------+----
| struct shared_context | extra | block1 | block2 | block3 | ...
+-----------------------+--------+--------+--------+--------+----
<-------- maxblocks --------->
* blocksize
The API allows to store content on several linked blocks. For example,
if you allocated blocks of 16 bytes, and you want to store an object of
60 bytes, the object will be allocated in a row of 4 blocks.
The API was made for LRU usage, each time you get an object, it pushes
the object at the end of the list. When it needs more space, it discards
The functions name have been renamed in a more logical way, the part
regarding shctx have been prefixed by shctx_ and the functions for the
shared ssl session cache have been prefixed by sh_ssl_sess_.
2017-10-30 19:08:51 +00:00
|
|
|
void shctx_row_inc_hot(struct shared_context *shctx, struct shared_block *first);
|
|
|
|
void shctx_row_dec_hot(struct shared_context *shctx, struct shared_block *first);
|
|
|
|
int shctx_row_data_append(struct shared_context *shctx,
|
2018-10-22 15:55:57 +00:00
|
|
|
struct shared_block *first, struct shared_block *from,
|
|
|
|
unsigned char *data, int len);
|
MEDIUM: shctx: separate ssl and shctx
This patch reorganize the shctx API in a generic storage API, separating
the shared SSL session handling from its core.
The shctx API only handles the generic data part, it does not know what
kind of data you use with it.
A shared_context is a storage structure allocated in a shared memory,
allowing its usage in a multithread or a multiprocess context.
The structure use 2 linked list, one containing the available blocks,
and another for the hot locked blocks. At initialization the available
list is filled with <maxblocks> blocks of size <blocksize>. An <extra>
space is initialized outside the list in case you need some specific
storage.
+-----------------------+--------+--------+--------+--------+----
| struct shared_context | extra | block1 | block2 | block3 | ...
+-----------------------+--------+--------+--------+--------+----
<-------- maxblocks --------->
* blocksize
The API allows to store content on several linked blocks. For example,
if you allocated blocks of 16 bytes, and you want to store an object of
60 bytes, the object will be allocated in a row of 4 blocks.
The API was made for LRU usage, each time you get an object, it pushes
the object at the end of the list. When it needs more space, it discards
The functions name have been renamed in a more logical way, the part
regarding shctx have been prefixed by shctx_ and the functions for the
shared ssl session cache have been prefixed by sh_ssl_sess_.
2017-10-30 19:08:51 +00:00
|
|
|
int shctx_row_data_get(struct shared_context *shctx, struct shared_block *first,
|
|
|
|
unsigned char *dst, int offset, int len);
|
2017-10-30 18:36:36 +00:00
|
|
|
|
|
|
|
|
2017-10-09 12:17:39 +00:00
|
|
|
/* Lock functions */
|
|
|
|
|
|
|
|
#if defined (USE_PRIVATE_CACHE)
|
|
|
|
|
2017-10-30 22:44:40 +00:00
|
|
|
#define shctx_lock(shctx)
|
|
|
|
#define shctx_unlock(shctx)
|
2017-10-09 12:17:39 +00:00
|
|
|
|
|
|
|
#elif defined (USE_PTHREAD_PSHARED)
|
|
|
|
extern int use_shared_mem;
|
|
|
|
|
2017-10-30 22:44:40 +00:00
|
|
|
#define shctx_lock(shctx) if (use_shared_mem) pthread_mutex_lock(&shctx->mutex)
|
|
|
|
#define shctx_unlock(shctx) if (use_shared_mem) pthread_mutex_unlock(&shctx->mutex)
|
2017-10-09 12:17:39 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
extern int use_shared_mem;
|
|
|
|
|
|
|
|
#ifdef USE_SYSCALL_FUTEX
|
2017-10-30 22:44:40 +00:00
|
|
|
static inline void _shctx_wait4lock(unsigned int *count, unsigned int *uaddr, int value)
|
2017-10-09 12:17:39 +00:00
|
|
|
{
|
|
|
|
syscall(SYS_futex, uaddr, FUTEX_WAIT, value, NULL, 0, 0);
|
|
|
|
}
|
|
|
|
|
2017-10-30 22:44:40 +00:00
|
|
|
static inline void _shctx_awakelocker(unsigned int *uaddr)
|
2017-10-09 12:17:39 +00:00
|
|
|
{
|
|
|
|
syscall(SYS_futex, uaddr, FUTEX_WAKE, 1, NULL, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* internal spin lock */
|
|
|
|
|
|
|
|
#if defined (__i486__) || defined (__i586__) || defined (__i686__) || defined (__x86_64__)
|
|
|
|
static inline void relax()
|
|
|
|
{
|
|
|
|
__asm volatile("rep;nop\n" ::: "memory");
|
|
|
|
}
|
|
|
|
#else /* if no x86_64 or i586 arch: use less optimized but generic asm */
|
|
|
|
static inline void relax()
|
|
|
|
{
|
|
|
|
__asm volatile("" ::: "memory");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-10-30 22:44:40 +00:00
|
|
|
static inline void _shctx_wait4lock(unsigned int *count, unsigned int *uaddr, int value)
|
2017-10-09 12:17:39 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < *count; i++) {
|
|
|
|
relax();
|
|
|
|
relax();
|
2020-05-01 11:05:29 +00:00
|
|
|
if (*uaddr != value)
|
|
|
|
return;
|
2017-10-09 12:17:39 +00:00
|
|
|
}
|
2020-05-01 11:15:32 +00:00
|
|
|
*count = (unsigned char)((*count << 1) + 1);
|
2017-10-09 12:17:39 +00:00
|
|
|
}
|
|
|
|
|
2017-10-30 22:44:40 +00:00
|
|
|
#define _shctx_awakelocker(a)
|
2017-10-09 12:17:39 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined (__i486__) || defined (__i586__) || defined (__i686__) || defined (__x86_64__)
|
|
|
|
static inline unsigned int xchg(unsigned int *ptr, unsigned int x)
|
|
|
|
{
|
|
|
|
__asm volatile("lock xchgl %0,%1"
|
|
|
|
: "=r" (x), "+m" (*ptr)
|
|
|
|
: "0" (x)
|
|
|
|
: "memory");
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int cmpxchg(unsigned int *ptr, unsigned int old, unsigned int new)
|
|
|
|
{
|
|
|
|
unsigned int ret;
|
|
|
|
|
|
|
|
__asm volatile("lock cmpxchgl %2,%1"
|
|
|
|
: "=a" (ret), "+m" (*ptr)
|
|
|
|
: "r" (new), "0" (old)
|
|
|
|
: "memory");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned char atomic_dec(unsigned int *ptr)
|
|
|
|
{
|
|
|
|
unsigned char ret;
|
|
|
|
__asm volatile("lock decl %0\n"
|
|
|
|
"setne %1\n"
|
|
|
|
: "+m" (*ptr), "=qm" (ret)
|
|
|
|
:
|
|
|
|
: "memory");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* if no x86_64 or i586 arch: use less optimized gcc >= 4.1 built-ins */
|
|
|
|
static inline unsigned int xchg(unsigned int *ptr, unsigned int x)
|
|
|
|
{
|
|
|
|
return __sync_lock_test_and_set(ptr, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int cmpxchg(unsigned int *ptr, unsigned int old, unsigned int new)
|
|
|
|
{
|
|
|
|
return __sync_val_compare_and_swap(ptr, old, new);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned char atomic_dec(unsigned int *ptr)
|
|
|
|
{
|
|
|
|
return __sync_sub_and_fetch(ptr, 1) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2017-10-30 22:44:40 +00:00
|
|
|
static inline void _shctx_lock(struct shared_context *shctx)
|
2017-10-09 12:17:39 +00:00
|
|
|
{
|
|
|
|
unsigned int x;
|
2020-05-01 11:15:32 +00:00
|
|
|
unsigned int count = 3;
|
2017-10-09 12:17:39 +00:00
|
|
|
|
|
|
|
x = cmpxchg(&shctx->waiters, 0, 1);
|
|
|
|
if (x) {
|
|
|
|
if (x != 2)
|
|
|
|
x = xchg(&shctx->waiters, 2);
|
|
|
|
|
|
|
|
while (x) {
|
2017-10-30 22:44:40 +00:00
|
|
|
_shctx_wait4lock(&count, &shctx->waiters, 2);
|
2017-10-09 12:17:39 +00:00
|
|
|
x = xchg(&shctx->waiters, 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-30 22:44:40 +00:00
|
|
|
static inline void _shctx_unlock(struct shared_context *shctx)
|
2017-10-09 12:17:39 +00:00
|
|
|
{
|
|
|
|
if (atomic_dec(&shctx->waiters)) {
|
|
|
|
shctx->waiters = 0;
|
2017-10-30 22:44:40 +00:00
|
|
|
_shctx_awakelocker(&shctx->waiters);
|
2017-10-09 12:17:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-30 22:44:40 +00:00
|
|
|
#define shctx_lock(shctx) if (use_shared_mem) _shctx_lock(shctx)
|
2017-10-09 12:17:39 +00:00
|
|
|
|
2017-10-30 22:44:40 +00:00
|
|
|
#define shctx_unlock(shctx) if (use_shared_mem) _shctx_unlock(shctx)
|
2017-10-09 12:17:39 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2017-10-30 18:36:36 +00:00
|
|
|
/* List Macros */
|
|
|
|
|
2018-10-22 15:55:57 +00:00
|
|
|
/*
|
|
|
|
* Insert <s> block after <head> which is not necessarily the head of a list,
|
|
|
|
* so between <head> and the next element after <head>.
|
|
|
|
*/
|
|
|
|
static inline void shctx_block_append_hot(struct shared_context *shctx,
|
|
|
|
struct list *head,
|
|
|
|
struct shared_block *s)
|
|
|
|
{
|
|
|
|
shctx->nbav--;
|
|
|
|
LIST_DEL(&s->list);
|
|
|
|
LIST_ADD(head, &s->list);
|
|
|
|
}
|
|
|
|
|
MEDIUM: shctx: separate ssl and shctx
This patch reorganize the shctx API in a generic storage API, separating
the shared SSL session handling from its core.
The shctx API only handles the generic data part, it does not know what
kind of data you use with it.
A shared_context is a storage structure allocated in a shared memory,
allowing its usage in a multithread or a multiprocess context.
The structure use 2 linked list, one containing the available blocks,
and another for the hot locked blocks. At initialization the available
list is filled with <maxblocks> blocks of size <blocksize>. An <extra>
space is initialized outside the list in case you need some specific
storage.
+-----------------------+--------+--------+--------+--------+----
| struct shared_context | extra | block1 | block2 | block3 | ...
+-----------------------+--------+--------+--------+--------+----
<-------- maxblocks --------->
* blocksize
The API allows to store content on several linked blocks. For example,
if you allocated blocks of 16 bytes, and you want to store an object of
60 bytes, the object will be allocated in a row of 4 blocks.
The API was made for LRU usage, each time you get an object, it pushes
the object at the end of the list. When it needs more space, it discards
The functions name have been renamed in a more logical way, the part
regarding shctx have been prefixed by shctx_ and the functions for the
shared ssl session cache have been prefixed by sh_ssl_sess_.
2017-10-30 19:08:51 +00:00
|
|
|
static inline void shctx_block_set_hot(struct shared_context *shctx,
|
2017-10-30 18:36:36 +00:00
|
|
|
struct shared_block *s)
|
|
|
|
{
|
MEDIUM: shctx: separate ssl and shctx
This patch reorganize the shctx API in a generic storage API, separating
the shared SSL session handling from its core.
The shctx API only handles the generic data part, it does not know what
kind of data you use with it.
A shared_context is a storage structure allocated in a shared memory,
allowing its usage in a multithread or a multiprocess context.
The structure use 2 linked list, one containing the available blocks,
and another for the hot locked blocks. At initialization the available
list is filled with <maxblocks> blocks of size <blocksize>. An <extra>
space is initialized outside the list in case you need some specific
storage.
+-----------------------+--------+--------+--------+--------+----
| struct shared_context | extra | block1 | block2 | block3 | ...
+-----------------------+--------+--------+--------+--------+----
<-------- maxblocks --------->
* blocksize
The API allows to store content on several linked blocks. For example,
if you allocated blocks of 16 bytes, and you want to store an object of
60 bytes, the object will be allocated in a row of 4 blocks.
The API was made for LRU usage, each time you get an object, it pushes
the object at the end of the list. When it needs more space, it discards
The functions name have been renamed in a more logical way, the part
regarding shctx have been prefixed by shctx_ and the functions for the
shared ssl session cache have been prefixed by sh_ssl_sess_.
2017-10-30 19:08:51 +00:00
|
|
|
shctx->nbav--;
|
|
|
|
LIST_DEL(&s->list);
|
|
|
|
LIST_ADDQ(&shctx->hot, &s->list);
|
2017-10-30 18:36:36 +00:00
|
|
|
}
|
|
|
|
|
MEDIUM: shctx: separate ssl and shctx
This patch reorganize the shctx API in a generic storage API, separating
the shared SSL session handling from its core.
The shctx API only handles the generic data part, it does not know what
kind of data you use with it.
A shared_context is a storage structure allocated in a shared memory,
allowing its usage in a multithread or a multiprocess context.
The structure use 2 linked list, one containing the available blocks,
and another for the hot locked blocks. At initialization the available
list is filled with <maxblocks> blocks of size <blocksize>. An <extra>
space is initialized outside the list in case you need some specific
storage.
+-----------------------+--------+--------+--------+--------+----
| struct shared_context | extra | block1 | block2 | block3 | ...
+-----------------------+--------+--------+--------+--------+----
<-------- maxblocks --------->
* blocksize
The API allows to store content on several linked blocks. For example,
if you allocated blocks of 16 bytes, and you want to store an object of
60 bytes, the object will be allocated in a row of 4 blocks.
The API was made for LRU usage, each time you get an object, it pushes
the object at the end of the list. When it needs more space, it discards
The functions name have been renamed in a more logical way, the part
regarding shctx have been prefixed by shctx_ and the functions for the
shared ssl session cache have been prefixed by sh_ssl_sess_.
2017-10-30 19:08:51 +00:00
|
|
|
static inline void shctx_block_set_avail(struct shared_context *shctx,
|
2017-10-30 18:36:36 +00:00
|
|
|
struct shared_block *s)
|
|
|
|
{
|
MEDIUM: shctx: separate ssl and shctx
This patch reorganize the shctx API in a generic storage API, separating
the shared SSL session handling from its core.
The shctx API only handles the generic data part, it does not know what
kind of data you use with it.
A shared_context is a storage structure allocated in a shared memory,
allowing its usage in a multithread or a multiprocess context.
The structure use 2 linked list, one containing the available blocks,
and another for the hot locked blocks. At initialization the available
list is filled with <maxblocks> blocks of size <blocksize>. An <extra>
space is initialized outside the list in case you need some specific
storage.
+-----------------------+--------+--------+--------+--------+----
| struct shared_context | extra | block1 | block2 | block3 | ...
+-----------------------+--------+--------+--------+--------+----
<-------- maxblocks --------->
* blocksize
The API allows to store content on several linked blocks. For example,
if you allocated blocks of 16 bytes, and you want to store an object of
60 bytes, the object will be allocated in a row of 4 blocks.
The API was made for LRU usage, each time you get an object, it pushes
the object at the end of the list. When it needs more space, it discards
The functions name have been renamed in a more logical way, the part
regarding shctx have been prefixed by shctx_ and the functions for the
shared ssl session cache have been prefixed by sh_ssl_sess_.
2017-10-30 19:08:51 +00:00
|
|
|
shctx->nbav++;
|
|
|
|
LIST_DEL(&s->list);
|
|
|
|
LIST_ADDQ(&shctx->avail, &s->list);
|
2017-10-30 18:36:36 +00:00
|
|
|
}
|
2017-10-09 12:17:39 +00:00
|
|
|
|
2012-09-03 09:14:36 +00:00
|
|
|
#endif /* SHCTX_H */
|
|
|
|
|