bpo-30832: Remove own implementation for thread-local storage (#2537) · python/cpython@aa0aa04 (original) (raw)

`@@ -81,14 +81,14 @@ PyThread_init_thread(void)

`

81

81

` or the size specified by the THREAD_STACK_SIZE macro. */

`

82

82

`static size_t _pythread_stacksize = 0;

`

83

83

``

84

``

`-

#ifdef _POSIX_THREADS

`

85

``

`-

#define PYTHREAD_NAME "pthread"

`

86

``

`-

#include "thread_pthread.h"

`

87

``

`-

#endif

`

88

``

-

89

``

`-

#ifdef NT_THREADS

`

90

``

`-

#define PYTHREAD_NAME "nt"

`

91

``

`-

#include "thread_nt.h"

`

``

84

`+

#if defined(_POSIX_THREADS)

`

``

85

`+

define PYTHREAD_NAME "pthread"

`

``

86

`+

include "thread_pthread.h"

`

``

87

`+

#elif defined(NT_THREADS)

`

``

88

`+

define PYTHREAD_NAME "nt"

`

``

89

`+

include "thread_nt.h"

`

``

90

`+

#else

`

``

91

`+

error "Require native thread feature. See https://bugs.python.org/issue30832"

`

92

92

`#endif

`

93

93

``

94

94

``

`@@ -114,13 +114,7 @@ PyThread_set_stacksize(size_t size)

`

114

114

`#endif

`

115

115

`}

`

116

116

``

117

``

`-

#ifndef Py_HAVE_NATIVE_TLS

`

118

``

`-

/* If the platform has not supplied a platform specific

`

119

``

`-

TLS implementation, provide our own.

`

120

117

``

121

``

`-

This code stolen from "thread_sgi.h", where it was the only

`

122

``

`-

implementation of an existing Python TLS API.

`

123

``

`-

*/

`

124

118

`/* ------------------------------------------------------------------------

`

125

119

`Per-thread data ("key") support.

`

126

120

``

`@@ -157,205 +151,6 @@ any of the other functions are called. There's also a hidden assumption

`

157

151

`that calls to PyThread_create_key() are serialized externally.

`

158

152

`------------------------------------------------------------------------ */

`

159

153

``

160

``

`-

/* A singly-linked list of struct key objects remembers all the key->value

`

161

``

`-

`

162

``

`-

`

163

``

`-

*/

`

164

``

`-

struct key {

`

165

``

`-

/* Next record in the list, or NULL if this is the last record. */

`

166

``

`-

struct key *next;

`

167

``

-

168

``

`-

/* The thread id, according to PyThread_get_thread_ident(). */

`

169

``

`-

unsigned long id;

`

170

``

-

171

``

`-

/* The key and its associated value. */

`

172

``

`-

int key;

`

173

``

`-

void *value;

`

174

``

`-

};

`

175

``

-

176

``

`-

static struct key *keyhead = NULL;

`

177

``

`-

static PyThread_type_lock keymutex = NULL;

`

178

``

`-

static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */

`

179

``

-

180

``

`-

/* Internal helper.

`

181

``

`-

`

182

``

`-

`

183

``

`-

`

184

``

`-

`

185

``

`-

`

186

``

`-

`

187

``

`-

`

188

``

`-

`

189

``

`-

`

190

``

`-

`

191

``

`-

`

192

``

`-

`

193

``

`-

`

194

``

`-

`

195

``

`-

`

196

``

`-

`

197

``

`-

`

198

``

`-

`

199

``

`-

`

200

``

`-

*/

`

201

``

`-

static struct key *

`

202

``

`-

find_key(int set_value, int key, void *value)

`

203

``

`-

{

`

204

``

`-

struct key *p, *prev_p;

`

205

``

`-

unsigned long id = PyThread_get_thread_ident();

`

206

``

-

207

``

`-

if (!keymutex)

`

208

``

`-

return NULL;

`

209

``

`-

PyThread_acquire_lock(keymutex, 1);

`

210

``

`-

prev_p = NULL;

`

211

``

`-

for (p = keyhead; p != NULL; p = p->next) {

`

212

``

`-

if (p->id == id && p->key == key) {

`

213

``

`-

if (set_value)

`

214

``

`-

p->value = value;

`

215

``

`-

goto Done;

`

216

``

`-

}

`

217

``

`-

/* Sanity check. These states should never happen but if

`

218

``

`-

`

219

``

`-

`

220

``

`-

`

221

``

`-

if (p == prev_p)

`

222

``

`-

Py_FatalError("tls find_key: small circular list(!)");

`

223

``

`-

prev_p = p;

`

224

``

`-

if (p->next == keyhead)

`

225

``

`-

Py_FatalError("tls find_key: circular list(!)");

`

226

``

`-

}

`

227

``

`-

if (!set_value && value == NULL) {

`

228

``

`-

assert(p == NULL);

`

229

``

`-

goto Done;

`

230

``

`-

}

`

231

``

`-

p = (struct key *)PyMem_RawMalloc(sizeof(struct key));

`

232

``

`-

if (p != NULL) {

`

233

``

`-

p->id = id;

`

234

``

`-

p->key = key;

`

235

``

`-

p->value = value;

`

236

``

`-

p->next = keyhead;

`

237

``

`-

keyhead = p;

`

238

``

`-

}

`

239

``

`-

Done:

`

240

``

`-

PyThread_release_lock(keymutex);

`

241

``

`-

return p;

`

242

``

`-

}

`

243

``

-

244

``

`-

/* Return a new key. This must be called before any other functions in

`

245

``

`-

`

246

``

`-

`

247

``

`-

*/

`

248

``

`-

int

`

249

``

`-

PyThread_create_key(void)

`

250

``

`-

{

`

251

``

`-

/* All parts of this function are wrong if it's called by multiple

`

252

``

`-

`

253

``

`-

*/

`

254

``

`-

if (keymutex == NULL)

`

255

``

`-

keymutex = PyThread_allocate_lock();

`

256

``

`-

return ++nkeys;

`

257

``

`-

}

`

258

``

-

259

``

`-

/* Forget the associations for key across all threads. */

`

260

``

`-

void

`

261

``

`-

PyThread_delete_key(int key)

`

262

``

`-

{

`

263

``

`-

struct key *p, **q;

`

264

``

-

265

``

`-

PyThread_acquire_lock(keymutex, 1);

`

266

``

`-

q = &keyhead;

`

267

``

`-

while ((p = *q) != NULL) {

`

268

``

`-

if (p->key == key) {

`

269

``

`-

*q = p->next;

`

270

``

`-

PyMem_RawFree((void *)p);

`

271

``

`-

/* NB This does not free p->value! */

`

272

``

`-

}

`

273

``

`-

else

`

274

``

`-

q = &p->next;

`

275

``

`-

}

`

276

``

`-

PyThread_release_lock(keymutex);

`

277

``

`-

}

`

278

``

-

279

``

`-

int

`

280

``

`-

PyThread_set_key_value(int key, void *value)

`

281

``

`-

{

`

282

``

`-

struct key *p;

`

283

``

-

284

``

`-

p = find_key(1, key, value);

`

285

``

`-

if (p == NULL)

`

286

``

`-

return -1;

`

287

``

`-

else

`

288

``

`-

return 0;

`

289

``

`-

}

`

290

``

-

291

``

`-

/* Retrieve the value associated with key in the current thread, or NULL

`

292

``

`-

`

293

``

`-

*/

`

294

``

`-

void *

`

295

``

`-

PyThread_get_key_value(int key)

`

296

``

`-

{

`

297

``

`-

struct key *p = find_key(0, key, NULL);

`

298

``

-

299

``

`-

if (p == NULL)

`

300

``

`-

return NULL;

`

301

``

`-

else

`

302

``

`-

return p->value;

`

303

``

`-

}

`

304

``

-

305

``

`-

/* Forget the current thread's association for key, if any. */

`

306

``

`-

void

`

307

``

`-

PyThread_delete_key_value(int key)

`

308

``

`-

{

`

309

``

`-

unsigned long id = PyThread_get_thread_ident();

`

310

``

`-

struct key *p, **q;

`

311

``

-

312

``

`-

PyThread_acquire_lock(keymutex, 1);

`

313

``

`-

q = &keyhead;

`

314

``

`-

while ((p = *q) != NULL) {

`

315

``

`-

if (p->key == key && p->id == id) {

`

316

``

`-

*q = p->next;

`

317

``

`-

PyMem_RawFree((void *)p);

`

318

``

`-

/* NB This does not free p->value! */

`

319

``

`-

break;

`

320

``

`-

}

`

321

``

`-

else

`

322

``

`-

q = &p->next;

`

323

``

`-

}

`

324

``

`-

PyThread_release_lock(keymutex);

`

325

``

`-

}

`

326

``

-

327

``

`-

/* Forget everything not associated with the current thread id.

`

328

``

`-

`

329

``

`-

`

330

``

`-

`

331

``

`-

*/

`

332

``

`-

void

`

333

``

`-

PyThread_ReInitTLS(void)

`

334

``

`-

{

`

335

``

`-

unsigned long id = PyThread_get_thread_ident();

`

336

``

`-

struct key *p, **q;

`

337

``

-

338

``

`-

if (!keymutex)

`

339

``

`-

return;

`

340

``

-

341

``

`-

/* As with interpreter_lock in PyEval_ReInitThreads()

`

342

``

`-

we just create a new lock without freeing the old one */

`

343

``

`-

keymutex = PyThread_allocate_lock();

`

344

``

-

345

``

`-

/* Delete all keys which do not match the current thread id */

`

346

``

`-

q = &keyhead;

`

347

``

`-

while ((p = *q) != NULL) {

`

348

``

`-

if (p->id != id) {

`

349

``

`-

*q = p->next;

`

350

``

`-

PyMem_RawFree((void *)p);

`

351

``

`-

/* NB This does not free p->value! */

`

352

``

`-

}

`

353

``

`-

else

`

354

``

`-

q = &p->next;

`

355

``

`-

}

`

356

``

`-

}

`

357

``

-

358

``

`-

#endif /* Py_HAVE_NATIVE_TLS */

`

359

154

``

360

155

`PyDoc_STRVAR(threadinfo__doc__,

`

361

156

`"sys.thread_info\n\

`