Coverage Report

Created: 2024-02-25 07:20

/src/libfshfs/libcthreads/libcthreads_read_write_lock.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Read/Write lock functions
3
 *
4
 * Copyright (C) 2012-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include <errno.h>
27
28
#if defined( _MSC_VER ) && defined( WINAPI ) && ( WINVER >= 0x0602 )
29
#include <Synchapi.h>
30
#endif
31
32
#if defined( HAVE_PTHREAD_H ) && !defined( WINAPI )
33
#include <pthread.h>
34
#endif
35
36
#include "libcthreads_libcerror.h"
37
#include "libcthreads_read_write_lock.h"
38
#include "libcthreads_types.h"
39
40
#if !defined( HAVE_LOCAL_LIBCTHREADS ) || defined( HAVE_MULTI_THREAD_SUPPORT )
41
42
/* Creates a read/write lock
43
 * Make sure the value read_write_lock is referencing, is set to NULL
44
 * Returns 1 if successful or -1 on error
45
 */
46
int libcthreads_read_write_lock_initialize(
47
     libcthreads_read_write_lock_t **read_write_lock,
48
     libcerror_error_t **error )
49
129k
{
50
129k
  libcthreads_internal_read_write_lock_t *internal_read_write_lock = NULL;
51
129k
  static char *function                                            = "libcthreads_read_write_lock_initialize";
52
53
#if defined( WINAPI ) && ( WINVER >= 0x0400 ) && ( WINVER < 0x0600 )
54
  DWORD error_code                                                 = 0;
55
56
#elif defined( HAVE_PTHREAD_H ) && !defined( WINAPI )
57
129k
  int pthread_result                                               = 0;
58
129k
#endif
59
60
129k
  if( read_write_lock == NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
65
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
66
0
     "%s: invalid read/write lock.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
129k
  if( *read_write_lock != NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
76
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
77
0
     "%s: invalid read/write lock value already set.",
78
0
     function );
79
80
0
    return( -1 );
81
0
  }
82
129k
  internal_read_write_lock = memory_allocate_structure(
83
129k
                              libcthreads_internal_read_write_lock_t );
84
85
129k
  if( internal_read_write_lock == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
91
0
     "%s: unable to create read/write lock.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
129k
  if( memory_set(
97
129k
       internal_read_write_lock,
98
129k
       0,
99
129k
       sizeof( libcthreads_internal_read_write_lock_t ) ) == NULL )
100
0
  {
101
0
    libcerror_error_set(
102
0
     error,
103
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
104
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
105
0
     "%s: unable to clear read/write lock.",
106
0
     function );
107
108
0
    memory_free(
109
0
     internal_read_write_lock );
110
111
0
    return( -1 );
112
0
  }
113
#if defined( WINAPI ) && ( WINVER >= 0x0600 )
114
  InitializeSRWLock(
115
   &( internal_read_write_lock->slim_read_write_lock ) );
116
117
#elif defined( WINAPI ) && ( WINVER >= 0x0400 )
118
  InitializeCriticalSection(
119
   &( internal_read_write_lock->write_critical_section ) );
120
121
  InitializeCriticalSection(
122
   &( internal_read_write_lock->read_critical_section ) );
123
124
  internal_read_write_lock->no_read_event_handle = CreateEvent(
125
                                                    NULL,
126
                                                    TRUE,
127
                                                    TRUE,
128
                                                    NULL );
129
130
  if( internal_read_write_lock->no_read_event_handle == NULL )
131
  {
132
    error_code = GetLastError();
133
134
    libcerror_system_set_error(
135
     error,
136
     error_code,
137
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
138
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
139
     "%s: unable to initialize no read event handle.",
140
     function );
141
142
    goto on_error;
143
  }
144
#elif defined( WINAPI )
145
146
#error libcthreads_read_write_lock_initialize for Windows earlier than NT4 not implemented
147
148
#elif defined( HAVE_PTHREAD_H )
149
129k
  pthread_result = pthread_rwlock_init(
150
129k
                    &( internal_read_write_lock->read_write_lock ),
151
129k
                    NULL );
152
153
129k
  switch( pthread_result )
154
129k
  {
155
129k
    case 0:
156
129k
      break;
157
158
0
    case EAGAIN:
159
0
      libcerror_error_set(
160
0
       error,
161
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
162
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
163
0
       "%s: unable to initialize read/write lock with error: Insufficient resources.",
164
0
       function );
165
166
0
      goto on_error;
167
168
0
    default:
169
0
      libcerror_system_set_error(
170
0
       error,
171
0
       pthread_result,
172
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
173
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
174
0
       "%s: unable to initialize read/write lock.",
175
0
       function );
176
177
0
      goto on_error;
178
129k
  }
179
129k
#endif
180
129k
  *read_write_lock = (libcthreads_read_write_lock_t *) internal_read_write_lock;
181
182
129k
  return( 1 );
183
184
0
on_error:
185
0
  if( internal_read_write_lock != NULL )
186
0
  {
187
#if defined( WINAPI ) && ( WINVER >= 0x0400 ) && ( WINVER < 0x0600 )
188
    DeleteCriticalSection(
189
     &( internal_read_write_lock->read_critical_section ) );
190
191
    DeleteCriticalSection(
192
     &( internal_read_write_lock->write_critical_section ) );
193
#endif
194
0
    memory_free(
195
0
     internal_read_write_lock );
196
0
  }
197
0
  return( -1 );
198
129k
}
199
200
/* Frees a read/write lock
201
 * Returns 1 if successful or -1 on error
202
 */
203
int libcthreads_read_write_lock_free(
204
     libcthreads_read_write_lock_t **read_write_lock,
205
     libcerror_error_t **error )
206
129k
{
207
129k
  libcthreads_internal_read_write_lock_t *internal_read_write_lock = NULL;
208
129k
  static char *function                                            = "libcthreads_read_write_lock_free";
209
129k
  int result                                                       = 1;
210
211
#if defined( WINAPI ) && ( WINVER >= 0x0400 ) && ( WINVER < 0x0600 )
212
  DWORD error_code                                                 = 0;
213
214
#elif defined( HAVE_PTHREAD_H ) && !defined( WINAPI )
215
129k
  int pthread_result                                               = 0;
216
129k
#endif
217
218
129k
  if( read_write_lock == NULL )
219
0
  {
220
0
    libcerror_error_set(
221
0
     error,
222
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
223
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
224
0
     "%s: invalid read/write lock.",
225
0
     function );
226
227
0
    return( -1 );
228
0
  }
229
129k
  if( *read_write_lock != NULL )
230
129k
  {
231
129k
    internal_read_write_lock = (libcthreads_internal_read_write_lock_t *) *read_write_lock;
232
129k
    *read_write_lock         = NULL;
233
234
#if defined( WINAPI ) && ( WINVER >= 0x0400 ) && ( WINVER < 0x0600 )
235
    if( CloseHandle(
236
         internal_read_write_lock->no_read_event_handle ) == 0 )
237
    {
238
      error_code = GetLastError();
239
240
      libcerror_system_set_error(
241
       error,
242
       error_code,
243
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
244
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
245
       "%s: unable to free no read event handle.",
246
       function );
247
248
      result = -1;
249
    }
250
    DeleteCriticalSection(
251
     &( internal_read_write_lock->read_critical_section ) );
252
253
    DeleteCriticalSection(
254
     &( internal_read_write_lock->write_critical_section ) );
255
256
#elif defined( WINAPI ) && ( WINVER < 0x0400 )
257
258
#error libcthreads_read_write_lock_free for Windows earlier than NT4 not implemented
259
260
#elif defined( HAVE_PTHREAD_H )
261
129k
    pthread_result = pthread_rwlock_destroy(
262
129k
                      &( internal_read_write_lock->read_write_lock ) );
263
264
129k
    switch( pthread_result )
265
129k
    {
266
129k
      case 0:
267
129k
        break;
268
269
0
      case EAGAIN:
270
0
        libcerror_error_set(
271
0
         error,
272
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
273
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
274
0
         "%s: unable to destroy read/write lock with error: Insufficient resources.",
275
0
         function );
276
277
0
        result = -1;
278
0
        break;
279
280
0
      case EBUSY:
281
0
        libcerror_error_set(
282
0
         error,
283
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
284
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
285
0
         "%s: unable to destroy read/write lock with error: Resource busy.",
286
0
         function );
287
288
0
        result = -1;
289
0
        break;
290
291
0
      default:
292
0
        libcerror_system_set_error(
293
0
         error,
294
0
         pthread_result,
295
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
296
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
297
0
         "%s: unable to destroy read/write lock.",
298
0
         function );
299
300
0
        result = -1;
301
0
        break;
302
129k
    }
303
129k
#endif
304
129k
    memory_free(
305
129k
     internal_read_write_lock );
306
129k
  }
307
129k
  return( result );
308
129k
}
309
310
/* Grabs a read/write lock for reading
311
 * Returns 1 if successful or -1 on error
312
 */
313
int libcthreads_read_write_lock_grab_for_read(
314
     libcthreads_read_write_lock_t *read_write_lock,
315
     libcerror_error_t **error )
316
65.6k
{
317
65.6k
  libcthreads_internal_read_write_lock_t *internal_read_write_lock = NULL;
318
65.6k
  static char *function                                            = "libcthreads_read_write_lock_grab_for_read";
319
320
#if defined( WINAPI ) && ( WINVER >= 0x0400 ) && ( WINVER < 0x0600 )
321
  DWORD error_code                                                 = 0;
322
  BOOL result                                                      = 0;
323
324
#elif defined( HAVE_PTHREAD_H ) && !defined( WINAPI )
325
65.6k
  int pthread_result                                               = 0;
326
65.6k
#endif
327
328
65.6k
  if( read_write_lock == NULL )
329
0
  {
330
0
    libcerror_error_set(
331
0
     error,
332
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
333
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
334
0
     "%s: invalid read/write lock.",
335
0
     function );
336
337
0
    return( -1 );
338
0
  }
339
65.6k
  internal_read_write_lock = (libcthreads_internal_read_write_lock_t *) read_write_lock;
340
341
#if defined( WINAPI ) && ( WINVER >= 0x0600 )
342
  AcquireSRWLockShared(
343
   &( internal_read_write_lock->slim_read_write_lock ) );
344
345
#elif defined( WINAPI ) && ( WINVER >= 0x0400 )
346
  EnterCriticalSection(
347
   &( internal_read_write_lock->write_critical_section ) );
348
349
  EnterCriticalSection(
350
   &( internal_read_write_lock->read_critical_section ) );
351
352
  internal_read_write_lock->number_of_readers++;
353
354
  if( internal_read_write_lock->number_of_readers == 1 )
355
  {
356
    result = ResetEvent(
357
              internal_read_write_lock->no_read_event_handle );
358
359
    if( result == 0 )
360
    {
361
      error_code = GetLastError();
362
363
      internal_read_write_lock->number_of_readers--;
364
    }
365
  }
366
  else
367
  {
368
    result = 1;
369
  }
370
  LeaveCriticalSection(
371
   &( internal_read_write_lock->read_critical_section ) );
372
373
  LeaveCriticalSection(
374
   &( internal_read_write_lock->write_critical_section ) );
375
376
  if( result == 0 )
377
  {
378
    libcerror_system_set_error(
379
     error,
380
     error_code,
381
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
382
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
383
     "%s: reset of no read event failed.",
384
     function );
385
386
    return( -1 );
387
  }
388
#elif defined( WINAPI )
389
390
#error libcthreads_read_write_lock_grab_for_read for Windows earlier than NT4 not implemented
391
392
#elif defined( HAVE_PTHREAD_H )
393
65.6k
  pthread_result = pthread_rwlock_rdlock(
394
65.6k
                    &( internal_read_write_lock->read_write_lock ) );
395
396
65.6k
  switch( pthread_result )
397
65.6k
  {
398
65.6k
    case 0:
399
65.6k
      break;
400
401
0
    case EAGAIN:
402
0
      libcerror_error_set(
403
0
       error,
404
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
405
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
406
0
       "%s: unable to lock read/write lock for read with error: Maximum number of locks exceeded.",
407
0
       function );
408
409
0
      return( -1 );
410
411
0
    case EDEADLK:
412
0
      libcerror_error_set(
413
0
       error,
414
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
415
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
416
0
       "%s: unable to lock read/write lock for read with error: Deadlock condition detected.",
417
0
       function );
418
419
0
      return( -1 );
420
421
0
    default:
422
0
      libcerror_system_set_error(
423
0
       error,
424
0
       pthread_result,
425
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
426
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
427
0
       "%s: unable to lock read/write lock for read.",
428
0
       function );
429
430
0
      return( -1 );
431
65.6k
  }
432
65.6k
#endif
433
65.6k
  return( 1 );
434
65.6k
}
435
436
/* Grabs a read/write lock for writing
437
 * Returns 1 if successful or -1 on error
438
 */
439
int libcthreads_read_write_lock_grab_for_write(
440
     libcthreads_read_write_lock_t *read_write_lock,
441
     libcerror_error_t **error )
442
142k
{
443
142k
  libcthreads_internal_read_write_lock_t *internal_read_write_lock = NULL;
444
142k
  static char *function                                            = "libcthreads_read_write_lock_grab_for_write";
445
446
#if defined( WINAPI ) && ( WINVER >= 0x0400 ) && ( WINVER < 0x0600 )
447
  DWORD error_code                                                 = 0;
448
  DWORD wait_status                                                = 0;
449
450
#elif defined( HAVE_PTHREAD_H ) && !defined( WINAPI )
451
142k
  int pthread_result                                               = 0;
452
142k
#endif
453
454
142k
  if( read_write_lock == NULL )
455
0
  {
456
0
    libcerror_error_set(
457
0
     error,
458
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
459
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
460
0
     "%s: invalid read/write lock.",
461
0
     function );
462
463
0
    return( -1 );
464
0
  }
465
142k
  internal_read_write_lock = (libcthreads_internal_read_write_lock_t *) read_write_lock;
466
467
#if defined( WINAPI ) && ( WINVER >= 0x0600 )
468
  AcquireSRWLockExclusive(
469
   &( internal_read_write_lock->slim_read_write_lock ) );
470
471
#elif defined( WINAPI ) && ( WINVER >= 0x0400 )
472
  EnterCriticalSection(
473
   &( internal_read_write_lock->write_critical_section ) );
474
475
  wait_status = WaitForSingleObject(
476
                 internal_read_write_lock->no_read_event_handle,
477
                 INFINITE );
478
479
  if( wait_status == WAIT_FAILED )
480
  {
481
    error_code = GetLastError();
482
483
    LeaveCriticalSection(
484
     &( internal_read_write_lock->write_critical_section ) );
485
486
    libcerror_system_set_error(
487
     error,
488
     error_code,
489
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
490
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
491
     "%s: wait for no read event handle failed.",
492
     function );
493
494
    return( -1 );
495
  }
496
#elif defined( WINAPI )
497
498
#error libcthreads_read_write_lock_grab_for_write for Windows earlier than NT4 not implemented
499
500
#elif defined( HAVE_PTHREAD_H )
501
142k
  pthread_result = pthread_rwlock_wrlock(
502
142k
                    &( internal_read_write_lock->read_write_lock ) );
503
504
142k
  switch( pthread_result )
505
142k
  {
506
142k
    case 0:
507
142k
      break;
508
509
0
    case EDEADLK:
510
0
      libcerror_error_set(
511
0
       error,
512
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
513
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
514
0
       "%s: unable to lock read/write lock for write with error: Deadlock condition detected.",
515
0
       function );
516
517
0
      return( -1 );
518
519
0
    default:
520
0
      libcerror_system_set_error(
521
0
       error,
522
0
       pthread_result,
523
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
524
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
525
0
       "%s: unable to lock read/write lock for write.",
526
0
       function );
527
528
0
      return( -1 );
529
142k
  }
530
142k
#endif
531
142k
  return( 1 );
532
142k
}
533
534
/* Releases a read/write lock for reading
535
 * Returns 1 if successful or -1 on error
536
 */
537
int libcthreads_read_write_lock_release_for_read(
538
     libcthreads_read_write_lock_t *read_write_lock,
539
     libcerror_error_t **error )
540
65.6k
{
541
65.6k
  libcthreads_internal_read_write_lock_t *internal_read_write_lock = NULL;
542
65.6k
  static char *function                                            = "libcthreads_read_write_lock_release_for_read";
543
544
#if defined( WINAPI ) && ( WINVER >= 0x0400 ) && ( WINVER < 0x0600 )
545
  DWORD error_code                                                 = 0;
546
  BOOL result                                                      = 0;
547
548
#elif defined( HAVE_PTHREAD_H ) && !defined( WINAPI )
549
65.6k
  int pthread_result                                               = 0;
550
65.6k
#endif
551
552
65.6k
  if( read_write_lock == NULL )
553
0
  {
554
0
    libcerror_error_set(
555
0
     error,
556
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
557
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
558
0
     "%s: invalid read/write lock.",
559
0
     function );
560
561
0
    return( -1 );
562
0
  }
563
65.6k
  internal_read_write_lock = (libcthreads_internal_read_write_lock_t *) read_write_lock;
564
565
#if defined( WINAPI ) && ( WINVER >= 0x0600 )
566
  ReleaseSRWLockShared(
567
   &( internal_read_write_lock->slim_read_write_lock ) );
568
569
#elif defined( WINAPI ) && ( WINVER >= 0x0400 )
570
  EnterCriticalSection(
571
   &( internal_read_write_lock->read_critical_section ) );
572
573
  internal_read_write_lock->number_of_readers--;
574
575
  if( internal_read_write_lock->number_of_readers == 0 )
576
  {
577
    result = SetEvent(
578
              internal_read_write_lock->no_read_event_handle );
579
580
    if( result == 0 )
581
    {
582
      error_code = GetLastError();
583
584
      internal_read_write_lock->number_of_readers++;
585
    }
586
  }
587
  else
588
  {
589
    result = 1;
590
  }
591
  LeaveCriticalSection(
592
   &( internal_read_write_lock->read_critical_section ) );
593
594
  if( result == 0 )
595
  {
596
    libcerror_system_set_error(
597
     error,
598
     error_code,
599
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
600
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
601
     "%s: set of no read event failed.",
602
     function );
603
604
    return( -1 );
605
  }
606
#elif defined( WINAPI )
607
608
#error libcthreads_read_write_lock_release_for_read for Windows earlier than NT4 not implemented
609
610
#elif defined( HAVE_PTHREAD_H )
611
65.6k
  pthread_result = pthread_rwlock_unlock(
612
65.6k
                    &( internal_read_write_lock->read_write_lock ) );
613
614
65.6k
  if( pthread_result != 0 )
615
0
  {
616
0
    libcerror_system_set_error(
617
0
     error,
618
0
     pthread_result,
619
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
620
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
621
0
     "%s: unable to unlock read/write lock.",
622
0
     function );
623
624
0
    return( -1 );
625
0
  }
626
65.6k
#endif
627
65.6k
  return( 1 );
628
65.6k
}
629
630
/* Releases a read/write lock for writing
631
 * Returns 1 if successful or -1 on error
632
 */
633
int libcthreads_read_write_lock_release_for_write(
634
     libcthreads_read_write_lock_t *read_write_lock,
635
     libcerror_error_t **error )
636
142k
{
637
142k
  libcthreads_internal_read_write_lock_t *internal_read_write_lock = NULL;
638
142k
  static char *function                                            = "libcthreads_read_write_lock_release_for_write";
639
640
142k
#if defined( HAVE_PTHREAD_H ) && !defined( WINAPI )
641
142k
  int pthread_result                                               = 0;
642
142k
#endif
643
644
142k
  if( read_write_lock == NULL )
645
0
  {
646
0
    libcerror_error_set(
647
0
     error,
648
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
649
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
650
0
     "%s: invalid read/write lock.",
651
0
     function );
652
653
0
    return( -1 );
654
0
  }
655
142k
  internal_read_write_lock = (libcthreads_internal_read_write_lock_t *) read_write_lock;
656
657
#if defined( WINAPI ) && ( WINVER >= 0x0600 )
658
  ReleaseSRWLockExclusive(
659
   &( internal_read_write_lock->slim_read_write_lock ) );
660
661
#elif defined( WINAPI ) && ( WINVER >= 0x0400 )
662
  LeaveCriticalSection(
663
   &( internal_read_write_lock->write_critical_section ) );
664
665
#elif defined( WINAPI )
666
667
#error libcthreads_read_write_lock_release_for_write for Windows earlier than NT4 not implemented
668
669
#elif defined( HAVE_PTHREAD_H )
670
142k
  pthread_result = pthread_rwlock_unlock(
671
142k
                    &( internal_read_write_lock->read_write_lock ) );
672
673
142k
  if( pthread_result != 0 )
674
0
  {
675
0
    libcerror_system_set_error(
676
0
     error,
677
0
     pthread_result,
678
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
679
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
680
0
     "%s: unable to unlock read/write lock.",
681
0
     function );
682
683
0
    return( -1 );
684
0
  }
685
142k
#endif
686
142k
  return( 1 );
687
142k
}
688
689
#endif /* !defined( HAVE_LOCAL_LIBCTHREADS ) || defined( HAVE_MULTI_THREAD_SUPPORT ) */
690