Print this page
5910 libnisdb won't build with modern GCC


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*

  23  * Copyright (c) 2001 by Sun Microsystems, Inc.
  24  * All rights reserved.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <stdio.h>
  30 #include <rpc/types.h>
  31 #include <rpc/xdr.h>
  32 #include "db_dictionary_c.h"
  33 #include "nisdb_rw.h"
  34 #include "nisdb_ldap.h"
  35 
  36 /*
  37  * Nesting-safe RW locking functions. Return 0 when successful, an
  38  * error number from the E-series when not.
  39  */
  40 
  41 int
  42 __nisdb_rwinit(__nisdb_rwlock_t *rw) {
  43 
  44         int     ret;
  45 
  46         if (rw == 0) {
  47 #ifdef  NISDB_MT_DEBUG
  48                 abort();


  90 find_reader(pthread_t id, __nisdb_rwlock_t *rw) {
  91 
  92         __nisdb_rl_t    *rr;
  93 
  94         for (rr = &rw->reader; rr != 0; rr = rr->next) {
  95                 if (rr->id == INV_PTHREAD_ID) {
  96                         rr = 0;
  97                         break;
  98                 }
  99                 if (rr->id == id)
 100                         break;
 101         }
 102 
 103         return (rr);
 104 }
 105 
 106 
 107 int
 108 __nisdb_rw_readlock_ok(__nisdb_rwlock_t *rw) {
 109         int             ret;
 110         pthread_t       myself = pthread_self();
 111         __nisdb_rl_t    *rr;
 112 
 113         if (rw == 0)
 114                 return (EFAULT);
 115 
 116         if (rw->destroyed != 0)
 117                 return (ESHUTDOWN);
 118 
 119         if ((ret = mutex_lock(&rw->mutex)) != 0)
 120                 return (ret);
 121 
 122         /*
 123          * Only allow changing 'force_write' when it's really safe; i.e.,
 124          * the lock hasn't been destroyed, and there are no readers.
 125          */
 126         if (rw->destroyed == 0 && rw->reader_count == 0) {
 127                 rw->force_write = 0;
 128                 ret = 0;
 129         } else {
 130                 ret = EBUSY;
 131         }
 132 
 133         (void) mutex_unlock(&rw->mutex);
 134 
 135         return (ret);
 136 }
 137 
 138 
 139 int
 140 __nisdb_rw_force_writelock(__nisdb_rwlock_t *rw) {
 141         int             ret;
 142         pthread_t       myself = pthread_self();
 143         __nisdb_rl_t    *rr;
 144 
 145         if (rw == 0 || rw->destroyed != 0)
 146                 return (ESHUTDOWN);
 147 
 148         if ((ret = mutex_lock(&rw->mutex)) != 0)
 149                 return (ret);
 150 
 151         /*
 152          * Only allow changing 'force_write' when it's really safe; i.e.,
 153          * the lock hasn't been destroyed, and there are no readers.
 154          */
 155         if (rw->destroyed == 0 && rw->reader_count == 0) {
 156                 rw->force_write = 1;
 157                 ret = 0;
 158         } else {
 159                 ret = EBUSY;
 160         }
 161 
 162         (void) mutex_unlock(&rw->mutex);
 163 


 189 
 190         if (rw->destroyed != 0) {
 191                 (void) mutex_unlock(&rw->mutex);
 192                 return (ESHUTDOWN);
 193         }
 194 
 195         /* Simplest (and probably most common) case: no readers or writers */
 196         if (rw->reader_count == 0 && rw->writer_count == 0) {
 197                 rw->writer_count = 1;
 198                 rw->writer.id = myself;
 199                 rw->writer.count = 1;
 200                 return (mutex_unlock(&rw->mutex));
 201         }
 202 
 203         /*
 204          * Need to know if we're holding a read lock already, and if
 205          * all other readers are blocked waiting for the mutex.
 206          */
 207         if (rw->reader_count > 0) {
 208                 if ((rr = find_reader(myself, rw)) != 0) {
 209                         if (rr->count)
 210                                 /*
 211                                  * We're already holding a read lock, so
 212                                  * if the number of readers equals the number
 213                                  * of blocked readers plus one, all other
 214                                  * readers are blocked.
 215                                  */
 216                                 if (rw->reader_count ==
 217                                                 (rw->reader_blocked + 1))
 218                                         all_readers_blocked = 1;
 219                         else
 220                                 /*
 221                                  * We're not holding a read lock, so the
 222                                  * number of readers should equal the number
 223                                  * of blocked readers if all readers are
 224                                  * blocked.
 225                                  */
 226                                 if (rw->reader_count == rw->reader_blocked)
 227                                         all_readers_blocked = 1;
 228                 }
 229         }

 230 
 231         /* Wait for reader(s) or writer to finish */
 232         while (1) {
 233                 /*
 234                  * We can stop looping if one of the following holds:
 235                  *      - No readers, no writers
 236                  *      - No writers (or writer is myself), and one of:
 237                  *              - No readers
 238                  *              - One reader, and it's us
 239                  *              - N readers, but all blocked on the mutex
 240                  */
 241                 if (
 242                         (rw->writer_count == 0 && rw->reader_count == 0) ||
 243                         ((rw->writer_count == 0 || rw->writer.id == myself) &&
 244                                 (rw->reader_count == 0) ||
 245                                 (rw->reader_count == 1 &&
 246                                         rw->reader.id == myself))) {
 247                         break;
 248                 }
 249                 /*
 250                  * Provided that all readers are blocked on the mutex
 251                  * we break a potential dead-lock by acquiring the
 252                  * write lock.
 253                  */
 254                 if (all_readers_blocked) {
 255                         if (rw->writer_count == 0 || rw->writer.id == myself) {
 256                                 break;
 257                         }
 258                 }
 259 
 260                 /*
 261                  * If 'trylock' is set, tell the caller that we'd have to
 262                  * block to obtain the lock.
 263                  */
 264                 if (trylock) {


 631 
 632         rr = &rw->reader;
 633         do {
 634                 if (rr->id == myself) {
 635                         (void) mutex_unlock(&rw->mutex);
 636                         return (0);
 637                 }
 638                 rr = rr->next;
 639         } while (rr != 0);
 640 
 641         ret = mutex_unlock(&rw->mutex);
 642         return ((ret == 0) ? EBUSY : ret);
 643 }
 644 
 645 
 646 int
 647 __nisdb_destroy_lock(__nisdb_rwlock_t *rw) {
 648 
 649         int             ret;
 650         pthread_t       myself = pthread_self();
 651         __nisdb_rl_t    *rr;
 652 
 653 
 654         if (rw == 0) {
 655 #ifdef  NISDB_MT_DEBUG
 656                 abort();
 657 #endif  /* NISDB_MT_DEBUG */
 658                 return (EFAULT);
 659         }
 660 
 661         if (rw->destroyed != 0)
 662                 return (ESHUTDOWN);
 663 
 664         if ((ret = mutex_lock(&rw->mutex)) != 0)
 665                 return (ret);
 666 
 667         if (rw->destroyed != 0) {
 668                 (void) mutex_unlock(&rw->mutex);
 669                 return (ESHUTDOWN);
 670         }
 671 
 672         /*
 673          * Only proceed if if there are neither readers nor writers
 674          * other than this thread. Also, no nested locks may be in
 675          * effect.
 676          */
 677         if ((rw->writer_count > 0 &&
 678                         (rw->writer.id != myself || rw->writer.count != 1) ||
 679                 (rw->reader_count > 0 &&
 680                         !(rw->reader_count == 1 && rw->reader.id == myself &&
 681                                 rw->reader.count == 1))) ||
 682                 (rw->writer_count > 0 && rw->reader_count > 0)) {
 683 #ifdef  NISDB_MT_DEBUG
 684                 abort();
 685 #endif  /* NISDB_MT_DEBUG */
 686                 (void) mutex_unlock(&rw->mutex);
 687                 return (ENOLCK);
 688         }
 689 
 690         /*
 691          * Mark lock destroyed, so that any thread waiting on the mutex
 692          * will know what's what. Of course, this is a bit iffy, since
 693          * we're probably being called from a destructor, and the structure
 694          * where we live will soon cease to exist (i.e., be freed and
 695          * perhaps re-used). Still, we can only do our best, and give
 696          * those other threads the best chance possible.
 697          */
 698         rw->destroyed++;




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2015 Gary Mills
  24  * Copyright (c) 2001 by Sun Microsystems, Inc.
  25  * All rights reserved.
  26  */
  27 


  28 #include <stdio.h>
  29 #include <rpc/types.h>
  30 #include <rpc/xdr.h>
  31 #include "db_dictionary_c.h"
  32 #include "nisdb_rw.h"
  33 #include "nisdb_ldap.h"
  34 
  35 /*
  36  * Nesting-safe RW locking functions. Return 0 when successful, an
  37  * error number from the E-series when not.
  38  */
  39 
  40 int
  41 __nisdb_rwinit(__nisdb_rwlock_t *rw) {
  42 
  43         int     ret;
  44 
  45         if (rw == 0) {
  46 #ifdef  NISDB_MT_DEBUG
  47                 abort();


  89 find_reader(pthread_t id, __nisdb_rwlock_t *rw) {
  90 
  91         __nisdb_rl_t    *rr;
  92 
  93         for (rr = &rw->reader; rr != 0; rr = rr->next) {
  94                 if (rr->id == INV_PTHREAD_ID) {
  95                         rr = 0;
  96                         break;
  97                 }
  98                 if (rr->id == id)
  99                         break;
 100         }
 101 
 102         return (rr);
 103 }
 104 
 105 
 106 int
 107 __nisdb_rw_readlock_ok(__nisdb_rwlock_t *rw) {
 108         int             ret;


 109 
 110         if (rw == 0)
 111                 return (EFAULT);
 112 
 113         if (rw->destroyed != 0)
 114                 return (ESHUTDOWN);
 115 
 116         if ((ret = mutex_lock(&rw->mutex)) != 0)
 117                 return (ret);
 118 
 119         /*
 120          * Only allow changing 'force_write' when it's really safe; i.e.,
 121          * the lock hasn't been destroyed, and there are no readers.
 122          */
 123         if (rw->destroyed == 0 && rw->reader_count == 0) {
 124                 rw->force_write = 0;
 125                 ret = 0;
 126         } else {
 127                 ret = EBUSY;
 128         }
 129 
 130         (void) mutex_unlock(&rw->mutex);
 131 
 132         return (ret);
 133 }
 134 
 135 
 136 int
 137 __nisdb_rw_force_writelock(__nisdb_rwlock_t *rw) {
 138         int             ret;


 139 
 140         if (rw == 0 || rw->destroyed != 0)
 141                 return (ESHUTDOWN);
 142 
 143         if ((ret = mutex_lock(&rw->mutex)) != 0)
 144                 return (ret);
 145 
 146         /*
 147          * Only allow changing 'force_write' when it's really safe; i.e.,
 148          * the lock hasn't been destroyed, and there are no readers.
 149          */
 150         if (rw->destroyed == 0 && rw->reader_count == 0) {
 151                 rw->force_write = 1;
 152                 ret = 0;
 153         } else {
 154                 ret = EBUSY;
 155         }
 156 
 157         (void) mutex_unlock(&rw->mutex);
 158 


 184 
 185         if (rw->destroyed != 0) {
 186                 (void) mutex_unlock(&rw->mutex);
 187                 return (ESHUTDOWN);
 188         }
 189 
 190         /* Simplest (and probably most common) case: no readers or writers */
 191         if (rw->reader_count == 0 && rw->writer_count == 0) {
 192                 rw->writer_count = 1;
 193                 rw->writer.id = myself;
 194                 rw->writer.count = 1;
 195                 return (mutex_unlock(&rw->mutex));
 196         }
 197 
 198         /*
 199          * Need to know if we're holding a read lock already, and if
 200          * all other readers are blocked waiting for the mutex.
 201          */
 202         if (rw->reader_count > 0) {
 203                 if ((rr = find_reader(myself, rw)) != 0) {
 204                         if (rr->count) {
 205                                 /*
 206                                  * We're already holding a read lock, so
 207                                  * if the number of readers equals the number
 208                                  * of blocked readers plus one, all other
 209                                  * readers are blocked.
 210                                  */
 211                                 if (rw->reader_count ==
 212                                                 (rw->reader_blocked + 1))
 213                                         all_readers_blocked = 1;
 214                         } else {
 215                                 /*
 216                                  * We're not holding a read lock, so the
 217                                  * number of readers should equal the number
 218                                  * of blocked readers if all readers are
 219                                  * blocked.
 220                                  */
 221                                 if (rw->reader_count == rw->reader_blocked)
 222                                         all_readers_blocked = 1;
 223                         }
 224                 }
 225         }
 226 
 227         /* Wait for reader(s) or writer to finish */
 228         while (1) {
 229                 /*
 230                  * We can stop looping if one of the following holds:
 231                  *      - No readers, no writers
 232                  *      - No writers (or writer is myself), and one of:
 233                  *              - No readers
 234                  *              - One reader, and it's us
 235                  *              - N readers, but all blocked on the mutex
 236                  */
 237                 if (
 238                     (rw->writer_count == 0 && rw->reader_count == 0) ||
 239                     (((rw->writer_count == 0 || rw->writer.id == myself) &&
 240                     (rw->reader_count == 0)) ||
 241                     (rw->reader_count == 1 &&
 242                     rw->reader.id == myself))) {
 243                         break;
 244                 }
 245                 /*
 246                  * Provided that all readers are blocked on the mutex
 247                  * we break a potential dead-lock by acquiring the
 248                  * write lock.
 249                  */
 250                 if (all_readers_blocked) {
 251                         if (rw->writer_count == 0 || rw->writer.id == myself) {
 252                                 break;
 253                         }
 254                 }
 255 
 256                 /*
 257                  * If 'trylock' is set, tell the caller that we'd have to
 258                  * block to obtain the lock.
 259                  */
 260                 if (trylock) {


 627 
 628         rr = &rw->reader;
 629         do {
 630                 if (rr->id == myself) {
 631                         (void) mutex_unlock(&rw->mutex);
 632                         return (0);
 633                 }
 634                 rr = rr->next;
 635         } while (rr != 0);
 636 
 637         ret = mutex_unlock(&rw->mutex);
 638         return ((ret == 0) ? EBUSY : ret);
 639 }
 640 
 641 
 642 int
 643 __nisdb_destroy_lock(__nisdb_rwlock_t *rw) {
 644 
 645         int             ret;
 646         pthread_t       myself = pthread_self();

 647 
 648 
 649         if (rw == 0) {
 650 #ifdef  NISDB_MT_DEBUG
 651                 abort();
 652 #endif  /* NISDB_MT_DEBUG */
 653                 return (EFAULT);
 654         }
 655 
 656         if (rw->destroyed != 0)
 657                 return (ESHUTDOWN);
 658 
 659         if ((ret = mutex_lock(&rw->mutex)) != 0)
 660                 return (ret);
 661 
 662         if (rw->destroyed != 0) {
 663                 (void) mutex_unlock(&rw->mutex);
 664                 return (ESHUTDOWN);
 665         }
 666 
 667         /*
 668          * Only proceed if if there are neither readers nor writers
 669          * other than this thread. Also, no nested locks may be in
 670          * effect.
 671          */
 672         if (((rw->writer_count > 0 &&
 673             (rw->writer.id != myself || rw->writer.count != 1)) ||
 674             (rw->reader_count > 0 &&
 675             !(rw->reader_count == 1 && rw->reader.id == myself &&
 676             rw->reader.count == 1))) ||
 677             (rw->writer_count > 0 && rw->reader_count > 0)) {
 678 #ifdef  NISDB_MT_DEBUG
 679                 abort();
 680 #endif  /* NISDB_MT_DEBUG */
 681                 (void) mutex_unlock(&rw->mutex);
 682                 return (ENOLCK);
 683         }
 684 
 685         /*
 686          * Mark lock destroyed, so that any thread waiting on the mutex
 687          * will know what's what. Of course, this is a bit iffy, since
 688          * we're probably being called from a destructor, and the structure
 689          * where we live will soon cease to exist (i.e., be freed and
 690          * perhaps re-used). Still, we can only do our best, and give
 691          * those other threads the best chance possible.
 692          */
 693         rw->destroyed++;