blob: 4f8c23f7f8ff4b4440e17e14836c49d078aadfa5 [file] [log] [blame]
Emeric Brun3e541d12012-09-03 11:14:36 +02001/*
Willy Tarreau334099c2020-06-03 18:38:48 +02002 * include/haproxy/shctx.h - shared context management functions for SSL
Emeric Brun3e541d12012-09-03 11:14:36 +02003 *
4 * Copyright (C) 2011-2012 EXCELIANCE
5 *
6 * Author: Emeric Brun - emeric@exceliance.fr
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
Willy Tarreau334099c2020-06-03 18:38:48 +020014#ifndef __HAPROXY_SHCTX_H
15#define __HAPROXY_SHCTX_H
William Lallemand24a7a752017-10-09 14:17:39 +020016
Willy Tarreauca367712021-06-15 15:03:19 +020017#include <haproxy/api.h>
Willy Tarreau853b2972020-05-27 18:01:47 +020018#include <haproxy/list.h>
Willy Tarreau334099c2020-06-03 18:38:48 +020019#include <haproxy/shctx-t.h>
Emeric Brun3e541d12012-09-03 11:14:36 +020020
William Lallemand24a7a752017-10-09 14:17:39 +020021#ifndef USE_PRIVATE_CACHE
22#ifdef USE_PTHREAD_PSHARED
23#include <pthread.h>
24#else
25#ifdef USE_SYSCALL_FUTEX
26#include <unistd.h>
27#include <linux/futex.h>
28#include <sys/syscall.h>
Emeric Brun3e541d12012-09-03 11:14:36 +020029#endif
Emeric Brun3e541d12012-09-03 11:14:36 +020030#endif
Willy Tarreauca367712021-06-15 15:03:19 +020031#else
32#include <haproxy/thread.h>
Emeric Brun786991e2012-11-26 18:37:12 +010033#endif
34
Frédéric Lécailleb7838af2018-10-22 16:21:39 +020035int shctx_init(struct shared_context **orig_shctx,
Frédéric Lécailleb80bc272018-10-25 20:31:40 +020036 int maxblocks, int blocksize, unsigned int maxobjsz,
37 int extra, int shared);
Frédéric Lécaille0bec8072018-10-22 17:55:57 +020038struct shared_block *shctx_row_reserve_hot(struct shared_context *shctx,
39 struct shared_block *last, int data_len);
William Lallemand4f45bb92017-10-30 20:08:51 +010040void shctx_row_inc_hot(struct shared_context *shctx, struct shared_block *first);
41void shctx_row_dec_hot(struct shared_context *shctx, struct shared_block *first);
42int shctx_row_data_append(struct shared_context *shctx,
Frédéric Lécaille0bec8072018-10-22 17:55:57 +020043 struct shared_block *first, struct shared_block *from,
44 unsigned char *data, int len);
William Lallemand4f45bb92017-10-30 20:08:51 +010045int shctx_row_data_get(struct shared_context *shctx, struct shared_block *first,
46 unsigned char *dst, int offset, int len);
Emeric Bruncaa19cc2014-05-07 16:10:18 +020047
William Lallemanded0b5ad2017-10-30 19:36:36 +010048
William Lallemand24a7a752017-10-09 14:17:39 +020049/* Lock functions */
50
51#if defined (USE_PRIVATE_CACHE)
Willy Tarreauca367712021-06-15 15:03:19 +020052extern int use_shared_mem;
William Lallemand24a7a752017-10-09 14:17:39 +020053
Willy Tarreauca367712021-06-15 15:03:19 +020054#define shctx_lock(shctx) if (use_shared_mem) HA_SPIN_LOCK(SHCTX_LOCK, &shctx->lock)
55#define shctx_unlock(shctx) if (use_shared_mem) HA_SPIN_UNLOCK(SHCTX_LOCK, &shctx->lock)
William Lallemand24a7a752017-10-09 14:17:39 +020056
57#elif defined (USE_PTHREAD_PSHARED)
58extern int use_shared_mem;
59
William Lallemanda3c77cf2017-10-30 23:44:40 +010060#define shctx_lock(shctx) if (use_shared_mem) pthread_mutex_lock(&shctx->mutex)
61#define shctx_unlock(shctx) if (use_shared_mem) pthread_mutex_unlock(&shctx->mutex)
William Lallemand24a7a752017-10-09 14:17:39 +020062
63#else
64extern int use_shared_mem;
65
66#ifdef USE_SYSCALL_FUTEX
William Lallemanda3c77cf2017-10-30 23:44:40 +010067static inline void _shctx_wait4lock(unsigned int *count, unsigned int *uaddr, int value)
William Lallemand24a7a752017-10-09 14:17:39 +020068{
69 syscall(SYS_futex, uaddr, FUTEX_WAIT, value, NULL, 0, 0);
70}
71
William Lallemanda3c77cf2017-10-30 23:44:40 +010072static inline void _shctx_awakelocker(unsigned int *uaddr)
William Lallemand24a7a752017-10-09 14:17:39 +020073{
74 syscall(SYS_futex, uaddr, FUTEX_WAKE, 1, NULL, 0, 0);
75}
76
77#else /* internal spin lock */
78
79#if defined (__i486__) || defined (__i586__) || defined (__i686__) || defined (__x86_64__)
80static inline void relax()
81{
82 __asm volatile("rep;nop\n" ::: "memory");
83}
84#else /* if no x86_64 or i586 arch: use less optimized but generic asm */
85static inline void relax()
86{
87 __asm volatile("" ::: "memory");
88}
89#endif
90
William Lallemanda3c77cf2017-10-30 23:44:40 +010091static inline void _shctx_wait4lock(unsigned int *count, unsigned int *uaddr, int value)
William Lallemand24a7a752017-10-09 14:17:39 +020092{
93 int i;
94
95 for (i = 0; i < *count; i++) {
96 relax();
97 relax();
Willy Tarreau3801bdc2020-05-01 13:05:29 +020098 if (*uaddr != value)
99 return;
William Lallemand24a7a752017-10-09 14:17:39 +0200100 }
Willy Tarreau86c6a922020-05-01 13:15:32 +0200101 *count = (unsigned char)((*count << 1) + 1);
William Lallemand24a7a752017-10-09 14:17:39 +0200102}
103
William Lallemanda3c77cf2017-10-30 23:44:40 +0100104#define _shctx_awakelocker(a)
William Lallemand24a7a752017-10-09 14:17:39 +0200105
106#endif
107
108#if defined (__i486__) || defined (__i586__) || defined (__i686__) || defined (__x86_64__)
109static inline unsigned int xchg(unsigned int *ptr, unsigned int x)
110{
111 __asm volatile("lock xchgl %0,%1"
112 : "=r" (x), "+m" (*ptr)
113 : "0" (x)
114 : "memory");
115 return x;
116}
117
118static inline unsigned int cmpxchg(unsigned int *ptr, unsigned int old, unsigned int new)
119{
120 unsigned int ret;
121
122 __asm volatile("lock cmpxchgl %2,%1"
123 : "=a" (ret), "+m" (*ptr)
124 : "r" (new), "0" (old)
125 : "memory");
126 return ret;
127}
128
129static inline unsigned char atomic_dec(unsigned int *ptr)
130{
131 unsigned char ret;
132 __asm volatile("lock decl %0\n"
133 "setne %1\n"
134 : "+m" (*ptr), "=qm" (ret)
135 :
136 : "memory");
137 return ret;
138}
139
140#else /* if no x86_64 or i586 arch: use less optimized gcc >= 4.1 built-ins */
141static inline unsigned int xchg(unsigned int *ptr, unsigned int x)
142{
143 return __sync_lock_test_and_set(ptr, x);
144}
145
146static inline unsigned int cmpxchg(unsigned int *ptr, unsigned int old, unsigned int new)
147{
148 return __sync_val_compare_and_swap(ptr, old, new);
149}
150
151static inline unsigned char atomic_dec(unsigned int *ptr)
152{
153 return __sync_sub_and_fetch(ptr, 1) ? 1 : 0;
154}
155
156#endif
157
William Lallemanda3c77cf2017-10-30 23:44:40 +0100158static inline void _shctx_lock(struct shared_context *shctx)
William Lallemand24a7a752017-10-09 14:17:39 +0200159{
160 unsigned int x;
Willy Tarreau86c6a922020-05-01 13:15:32 +0200161 unsigned int count = 3;
William Lallemand24a7a752017-10-09 14:17:39 +0200162
163 x = cmpxchg(&shctx->waiters, 0, 1);
164 if (x) {
165 if (x != 2)
166 x = xchg(&shctx->waiters, 2);
167
168 while (x) {
William Lallemanda3c77cf2017-10-30 23:44:40 +0100169 _shctx_wait4lock(&count, &shctx->waiters, 2);
William Lallemand24a7a752017-10-09 14:17:39 +0200170 x = xchg(&shctx->waiters, 2);
171 }
172 }
173}
174
William Lallemanda3c77cf2017-10-30 23:44:40 +0100175static inline void _shctx_unlock(struct shared_context *shctx)
William Lallemand24a7a752017-10-09 14:17:39 +0200176{
177 if (atomic_dec(&shctx->waiters)) {
178 shctx->waiters = 0;
William Lallemanda3c77cf2017-10-30 23:44:40 +0100179 _shctx_awakelocker(&shctx->waiters);
William Lallemand24a7a752017-10-09 14:17:39 +0200180 }
181}
182
William Lallemanda3c77cf2017-10-30 23:44:40 +0100183#define shctx_lock(shctx) if (use_shared_mem) _shctx_lock(shctx)
William Lallemand24a7a752017-10-09 14:17:39 +0200184
William Lallemanda3c77cf2017-10-30 23:44:40 +0100185#define shctx_unlock(shctx) if (use_shared_mem) _shctx_unlock(shctx)
William Lallemand24a7a752017-10-09 14:17:39 +0200186
187#endif
188
William Lallemanded0b5ad2017-10-30 19:36:36 +0100189/* List Macros */
190
Frédéric Lécaille0bec8072018-10-22 17:55:57 +0200191/*
192 * Insert <s> block after <head> which is not necessarily the head of a list,
193 * so between <head> and the next element after <head>.
194 */
195static inline void shctx_block_append_hot(struct shared_context *shctx,
196 struct list *head,
197 struct shared_block *s)
198{
199 shctx->nbav--;
Willy Tarreau2b718102021-04-21 07:32:39 +0200200 LIST_DELETE(&s->list);
201 LIST_INSERT(head, &s->list);
Frédéric Lécaille0bec8072018-10-22 17:55:57 +0200202}
203
William Lallemand4f45bb92017-10-30 20:08:51 +0100204static inline void shctx_block_set_hot(struct shared_context *shctx,
William Lallemanded0b5ad2017-10-30 19:36:36 +0100205 struct shared_block *s)
206{
William Lallemand4f45bb92017-10-30 20:08:51 +0100207 shctx->nbav--;
Willy Tarreau2b718102021-04-21 07:32:39 +0200208 LIST_DELETE(&s->list);
209 LIST_APPEND(&shctx->hot, &s->list);
William Lallemanded0b5ad2017-10-30 19:36:36 +0100210}
211
William Lallemand4f45bb92017-10-30 20:08:51 +0100212static inline void shctx_block_set_avail(struct shared_context *shctx,
William Lallemanded0b5ad2017-10-30 19:36:36 +0100213 struct shared_block *s)
214{
William Lallemand4f45bb92017-10-30 20:08:51 +0100215 shctx->nbav++;
Willy Tarreau2b718102021-04-21 07:32:39 +0200216 LIST_DELETE(&s->list);
217 LIST_APPEND(&shctx->avail, &s->list);
William Lallemanded0b5ad2017-10-30 19:36:36 +0100218}
William Lallemand24a7a752017-10-09 14:17:39 +0200219
Willy Tarreau334099c2020-06-03 18:38:48 +0200220#endif /* __HAPROXY_SHCTX_H */
Emeric Brun3e541d12012-09-03 11:14:36 +0200221