blob: b258f3ce01e8e3dac42d4b9fb3a31e4b7b7a28f3 [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 Tarreau334099c2020-06-03 18:38:48 +020017#include <haproxy/api-t.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
Emeric Brun786991e2012-11-26 18:37:12 +010031#endif
32
Frédéric Lécailleb7838af2018-10-22 16:21:39 +020033int shctx_init(struct shared_context **orig_shctx,
Frédéric Lécailleb80bc272018-10-25 20:31:40 +020034 int maxblocks, int blocksize, unsigned int maxobjsz,
35 int extra, int shared);
Frédéric Lécaille0bec8072018-10-22 17:55:57 +020036struct shared_block *shctx_row_reserve_hot(struct shared_context *shctx,
37 struct shared_block *last, int data_len);
William Lallemand4f45bb92017-10-30 20:08:51 +010038void shctx_row_inc_hot(struct shared_context *shctx, struct shared_block *first);
39void shctx_row_dec_hot(struct shared_context *shctx, struct shared_block *first);
40int shctx_row_data_append(struct shared_context *shctx,
Frédéric Lécaille0bec8072018-10-22 17:55:57 +020041 struct shared_block *first, struct shared_block *from,
42 unsigned char *data, int len);
William Lallemand4f45bb92017-10-30 20:08:51 +010043int shctx_row_data_get(struct shared_context *shctx, struct shared_block *first,
44 unsigned char *dst, int offset, int len);
Emeric Bruncaa19cc2014-05-07 16:10:18 +020045
William Lallemanded0b5ad2017-10-30 19:36:36 +010046
William Lallemand24a7a752017-10-09 14:17:39 +020047/* Lock functions */
48
49#if defined (USE_PRIVATE_CACHE)
50
William Lallemanda3c77cf2017-10-30 23:44:40 +010051#define shctx_lock(shctx)
52#define shctx_unlock(shctx)
William Lallemand24a7a752017-10-09 14:17:39 +020053
54#elif defined (USE_PTHREAD_PSHARED)
55extern int use_shared_mem;
56
William Lallemanda3c77cf2017-10-30 23:44:40 +010057#define shctx_lock(shctx) if (use_shared_mem) pthread_mutex_lock(&shctx->mutex)
58#define shctx_unlock(shctx) if (use_shared_mem) pthread_mutex_unlock(&shctx->mutex)
William Lallemand24a7a752017-10-09 14:17:39 +020059
60#else
61extern int use_shared_mem;
62
63#ifdef USE_SYSCALL_FUTEX
William Lallemanda3c77cf2017-10-30 23:44:40 +010064static inline void _shctx_wait4lock(unsigned int *count, unsigned int *uaddr, int value)
William Lallemand24a7a752017-10-09 14:17:39 +020065{
66 syscall(SYS_futex, uaddr, FUTEX_WAIT, value, NULL, 0, 0);
67}
68
William Lallemanda3c77cf2017-10-30 23:44:40 +010069static inline void _shctx_awakelocker(unsigned int *uaddr)
William Lallemand24a7a752017-10-09 14:17:39 +020070{
71 syscall(SYS_futex, uaddr, FUTEX_WAKE, 1, NULL, 0, 0);
72}
73
74#else /* internal spin lock */
75
76#if defined (__i486__) || defined (__i586__) || defined (__i686__) || defined (__x86_64__)
77static inline void relax()
78{
79 __asm volatile("rep;nop\n" ::: "memory");
80}
81#else /* if no x86_64 or i586 arch: use less optimized but generic asm */
82static inline void relax()
83{
84 __asm volatile("" ::: "memory");
85}
86#endif
87
William Lallemanda3c77cf2017-10-30 23:44:40 +010088static inline void _shctx_wait4lock(unsigned int *count, unsigned int *uaddr, int value)
William Lallemand24a7a752017-10-09 14:17:39 +020089{
90 int i;
91
92 for (i = 0; i < *count; i++) {
93 relax();
94 relax();
Willy Tarreau3801bdc2020-05-01 13:05:29 +020095 if (*uaddr != value)
96 return;
William Lallemand24a7a752017-10-09 14:17:39 +020097 }
Willy Tarreau86c6a922020-05-01 13:15:32 +020098 *count = (unsigned char)((*count << 1) + 1);
William Lallemand24a7a752017-10-09 14:17:39 +020099}
100
William Lallemanda3c77cf2017-10-30 23:44:40 +0100101#define _shctx_awakelocker(a)
William Lallemand24a7a752017-10-09 14:17:39 +0200102
103#endif
104
105#if defined (__i486__) || defined (__i586__) || defined (__i686__) || defined (__x86_64__)
106static inline unsigned int xchg(unsigned int *ptr, unsigned int x)
107{
108 __asm volatile("lock xchgl %0,%1"
109 : "=r" (x), "+m" (*ptr)
110 : "0" (x)
111 : "memory");
112 return x;
113}
114
115static inline unsigned int cmpxchg(unsigned int *ptr, unsigned int old, unsigned int new)
116{
117 unsigned int ret;
118
119 __asm volatile("lock cmpxchgl %2,%1"
120 : "=a" (ret), "+m" (*ptr)
121 : "r" (new), "0" (old)
122 : "memory");
123 return ret;
124}
125
126static inline unsigned char atomic_dec(unsigned int *ptr)
127{
128 unsigned char ret;
129 __asm volatile("lock decl %0\n"
130 "setne %1\n"
131 : "+m" (*ptr), "=qm" (ret)
132 :
133 : "memory");
134 return ret;
135}
136
137#else /* if no x86_64 or i586 arch: use less optimized gcc >= 4.1 built-ins */
138static inline unsigned int xchg(unsigned int *ptr, unsigned int x)
139{
140 return __sync_lock_test_and_set(ptr, x);
141}
142
143static inline unsigned int cmpxchg(unsigned int *ptr, unsigned int old, unsigned int new)
144{
145 return __sync_val_compare_and_swap(ptr, old, new);
146}
147
148static inline unsigned char atomic_dec(unsigned int *ptr)
149{
150 return __sync_sub_and_fetch(ptr, 1) ? 1 : 0;
151}
152
153#endif
154
William Lallemanda3c77cf2017-10-30 23:44:40 +0100155static inline void _shctx_lock(struct shared_context *shctx)
William Lallemand24a7a752017-10-09 14:17:39 +0200156{
157 unsigned int x;
Willy Tarreau86c6a922020-05-01 13:15:32 +0200158 unsigned int count = 3;
William Lallemand24a7a752017-10-09 14:17:39 +0200159
160 x = cmpxchg(&shctx->waiters, 0, 1);
161 if (x) {
162 if (x != 2)
163 x = xchg(&shctx->waiters, 2);
164
165 while (x) {
William Lallemanda3c77cf2017-10-30 23:44:40 +0100166 _shctx_wait4lock(&count, &shctx->waiters, 2);
William Lallemand24a7a752017-10-09 14:17:39 +0200167 x = xchg(&shctx->waiters, 2);
168 }
169 }
170}
171
William Lallemanda3c77cf2017-10-30 23:44:40 +0100172static inline void _shctx_unlock(struct shared_context *shctx)
William Lallemand24a7a752017-10-09 14:17:39 +0200173{
174 if (atomic_dec(&shctx->waiters)) {
175 shctx->waiters = 0;
William Lallemanda3c77cf2017-10-30 23:44:40 +0100176 _shctx_awakelocker(&shctx->waiters);
William Lallemand24a7a752017-10-09 14:17:39 +0200177 }
178}
179
William Lallemanda3c77cf2017-10-30 23:44:40 +0100180#define shctx_lock(shctx) if (use_shared_mem) _shctx_lock(shctx)
William Lallemand24a7a752017-10-09 14:17:39 +0200181
William Lallemanda3c77cf2017-10-30 23:44:40 +0100182#define shctx_unlock(shctx) if (use_shared_mem) _shctx_unlock(shctx)
William Lallemand24a7a752017-10-09 14:17:39 +0200183
184#endif
185
William Lallemanded0b5ad2017-10-30 19:36:36 +0100186/* List Macros */
187
Frédéric Lécaille0bec8072018-10-22 17:55:57 +0200188/*
189 * Insert <s> block after <head> which is not necessarily the head of a list,
190 * so between <head> and the next element after <head>.
191 */
192static inline void shctx_block_append_hot(struct shared_context *shctx,
193 struct list *head,
194 struct shared_block *s)
195{
196 shctx->nbav--;
197 LIST_DEL(&s->list);
198 LIST_ADD(head, &s->list);
199}
200
William Lallemand4f45bb92017-10-30 20:08:51 +0100201static inline void shctx_block_set_hot(struct shared_context *shctx,
William Lallemanded0b5ad2017-10-30 19:36:36 +0100202 struct shared_block *s)
203{
William Lallemand4f45bb92017-10-30 20:08:51 +0100204 shctx->nbav--;
205 LIST_DEL(&s->list);
206 LIST_ADDQ(&shctx->hot, &s->list);
William Lallemanded0b5ad2017-10-30 19:36:36 +0100207}
208
William Lallemand4f45bb92017-10-30 20:08:51 +0100209static inline void shctx_block_set_avail(struct shared_context *shctx,
William Lallemanded0b5ad2017-10-30 19:36:36 +0100210 struct shared_block *s)
211{
William Lallemand4f45bb92017-10-30 20:08:51 +0100212 shctx->nbav++;
213 LIST_DEL(&s->list);
214 LIST_ADDQ(&shctx->avail, &s->list);
William Lallemanded0b5ad2017-10-30 19:36:36 +0100215}
William Lallemand24a7a752017-10-09 14:17:39 +0200216
Willy Tarreau334099c2020-06-03 18:38:48 +0200217#endif /* __HAPROXY_SHCTX_H */
Emeric Brun3e541d12012-09-03 11:14:36 +0200218