Annotation of libaitio/src/exec.c, revision 1.1.2.23

1.1.2.1   misho       1: #include "global.h"
                      2: 
                      3: 
                      4: /*
                      5:  * io_progInit() - Init program pool
                      6:  *
                      7:  * @progName = program name for execution
                      8:  * @initNum = initial started programs
                      9:  * @maxNum = maximum started programs
                     10:  * return: NULL error or !=NULL allocated pool (must destroied with io_progDestroy())
                     11:  */
                     12: prog_t *
                     13: io_progInit(const char *progName, u_int initNum, u_int maxNum)
                     14: {
                     15:        prog_t *prg = NULL;
                     16: 
                     17:        if (initNum > maxNum)
                     18:                return NULL;
                     19: 
                     20:        prg = e_malloc(sizeof(prog_t));
                     21:        if (!prg) {
                     22:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                     23:                return NULL;
                     24:        } else
                     25:                memset(prg, 0, sizeof(prog_t));
                     26: 
                     27:        prg->prog_inin = initNum;
                     28:        prg->prog_maxn = maxNum;
                     29:        strlcpy(prg->prog_name, progName, sizeof prg->prog_name);
                     30: 
1.1.2.9   misho      31:        prg->prog_used = e_malloc(E_ALIGN(prg->prog_maxn, sizeof *prg->prog_used) / 
                     32:                        sizeof *prg->prog_used);
                     33:        if (!prg->prog_used) {
                     34:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                     35:                e_free(prg);
                     36:                return NULL;
                     37:        }
                     38: 
1.1.2.1   misho      39:        prg->prog_fds = array_Init(prg->prog_maxn);
                     40:        if (!prg->prog_fds) {
                     41:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.1.2.9   misho      42:                e_free(prg->prog_used);
1.1.2.1   misho      43:                e_free(prg);
                     44:                return NULL;
                     45:        }
                     46: 
                     47:        pthread_mutex_init(&prg->prog_mtx, NULL);
1.1.2.12  misho      48:        signal(SIGPIPE, SIG_IGN);
1.1.2.2   misho      49: 
1.1.2.6   misho      50:        if (io_progOpen(prg, prg->prog_inin) < 0) {
1.1.2.2   misho      51:                io_progDestroy(&prg);
1.1.2.6   misho      52:                prg = NULL;
                     53:        }
1.1.2.1   misho      54:        return prg;
                     55: }
                     56: 
                     57: /*
                     58:  * io_progDestroy() - Destroy entire program pool
                     59:  *
                     60:  * @pprg = program pool
                     61:  * return: none
                     62:  */
                     63: void
                     64: io_progDestroy(prog_t ** __restrict pprg)
                     65: {
                     66:        if (!pprg || !*pprg)
                     67:                return;
                     68: 
                     69:        io_progClose(*pprg, 0);
                     70: 
1.1.2.9   misho      71:        e_free((*pprg)->prog_used);
1.1.2.1   misho      72:        array_Destroy(&(*pprg)->prog_fds);
                     73:        pthread_mutex_destroy(&(*pprg)->prog_mtx);
1.1.2.13  misho      74:        signal(SIGPIPE, SIG_DFL);
1.1.2.1   misho      75: 
                     76:        e_free(*pprg);
                     77:        *pprg = NULL;
                     78: }
                     79: 
                     80: /*
                     81:  * io_progClose() - Close all programs in pool
                     82:  *
                     83:  * @prg = program pool
                     84:  * @closeNum = close program(s) (0 all)
                     85:  * return: 0 error, >0 closed programs
                     86:  */
                     87: int
                     88: io_progClose(prog_t * __restrict prg, u_int closeNum)
                     89: {
                     90:        register int i;
                     91:        int ret = 0;
1.1.2.14  misho      92:        struct tagPIOPID *p;
1.1.2.1   misho      93: 
                     94:        if (!prg)
                     95:                return 0;
                     96:        if (closeNum > prg->prog_maxn) {
                     97:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                     98:                return 0;
                     99:        }
                    100: 
                    101:        pthread_mutex_lock(&prg->prog_mtx);
                    102:        for (i = array_Size(prg->prog_fds) - 1; 
                    103:                        (closeNum ? ret < closeNum : 42) && i > -1; i--)
1.1.2.14  misho     104:                if (array_Get(prg->prog_fds, i) && 
                    105: #ifdef POPEN_STREAM
                    106:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
                    107: #else
                    108:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
                    109: #endif
                    110:                        kill(p->pid, SIGTERM);
                    111:                        usleep(1000);
                    112:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    113:                                kill(p->pid, SIGKILL);
1.1.2.11  misho     114: #ifdef POPEN_STREAM
1.1.2.6   misho     115:                        e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11  misho     116: #else
                    117:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    118: #endif
1.1.2.1   misho     119:                        array_Del(prg->prog_fds, i, 0);
1.1.2.9   misho     120:                        clrbit(prg->prog_used, i);
1.1.2.1   misho     121:                        prg->prog_cnum--;
                    122:                        ret++;
                    123:                }
                    124:        pthread_mutex_unlock(&prg->prog_mtx);
                    125: 
                    126:        return ret;
                    127: }
                    128: 
                    129: /*
1.1.2.14  misho     130:  * io_progCloseAt() - Close program at pool of certain position
                    131:  *
                    132:  * @prg = program pool
                    133:  * @idx = index at pool
                    134:  * return: 0 error or !=0 closed program
                    135:  */
                    136: int
                    137: io_progCloseAt(prog_t * __restrict prg, u_int idx)
                    138: {
                    139:        int ret = 0;
                    140:        struct tagPIOPID *p;
                    141: 
                    142:        if (!prg)
                    143:                return 0;
                    144:        if (idx > prg->prog_maxn) {
                    145:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                    146:                return 0;
                    147:        }
                    148: 
                    149:        pthread_mutex_lock(&prg->prog_mtx);
                    150:        if (array_Get(prg->prog_fds, idx) && 
                    151: #ifdef POPEN_STREAM
                    152:                        (p = pio_pgetpid(array(prg->prog_fds, idx, FILE*)))) {
                    153: #else
                    154:                        (p = pio_pgetpid((int) array(prg->prog_fds, idx, intptr_t)))) {
                    155: #endif
                    156:                kill(p->pid, SIGTERM);
                    157:                usleep(1000);
                    158:                if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    159:                        kill(p->pid, SIGKILL);
                    160: #ifdef POPEN_STREAM
                    161:                e_pclose(array(prg->prog_fds, idx, FILE*));
                    162: #else
                    163:                e_pclose((int) array(prg->prog_fds, idx, intptr_t));
                    164: #endif
                    165:                array_Del(prg->prog_fds, idx, 0);
                    166:                clrbit(prg->prog_used, idx);
                    167:                prg->prog_cnum--;
                    168:                ret++;
                    169:        }
                    170:        pthread_mutex_unlock(&prg->prog_mtx);
                    171: 
                    172:        return ret;
                    173: }
                    174: 
                    175: /*
1.1.2.22  misho     176:  * io_progCloseOf() - Close program at pool with certain handle
                    177:  *
                    178:  * @prg = program pool
                    179:  * @h = handle of program
                    180:  * return: 0 error, >0 closed programs
                    181:  */
                    182: int
                    183: #ifdef POPEN_STREAM
                    184: io_progCloseOf(prog_t * __restrict prg, FILE *h)
                    185: #else
                    186: io_progCloseOf(prog_t * __restrict prg, int h)
                    187: #endif
                    188: {
                    189:        register int i;
                    190:        int ret = 0;
                    191:        struct tagPIOPID *p;
                    192: #ifdef POPEN_STREAM
                    193:        FILE *f;
                    194: #else
                    195:        int f;
                    196: #endif
                    197: 
                    198:        if (!prg)
                    199:                return 0;
                    200: 
                    201:        pthread_mutex_lock(&prg->prog_mtx);
                    202:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    203:                if (array_Get(prg->prog_fds, i)) {
                    204: #ifdef POPEN_STREAM
                    205:                        f = array(prg->prog_fds, i, FILE*);
                    206:                        if (f == h && (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
                    207: #else
                    208:                        f = (int) array(prg->prog_fds, i, intptr_t);
                    209:                        if (f == h && (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
                    210: #endif
                    211:                                kill(p->pid, SIGTERM);
                    212:                                usleep(1000);
                    213:                                if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    214:                                        kill(p->pid, SIGKILL);
                    215: #ifdef POPEN_STREAM
                    216:                                e_pclose(array(prg->prog_fds, i, FILE*));
                    217: #else
                    218:                                e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    219: #endif
                    220:                                array_Del(prg->prog_fds, i, 0);
                    221:                                clrbit(prg->prog_used, i);
                    222:                                prg->prog_cnum--;
                    223:                                ret++;
                    224:                                break;
                    225:                        }
                    226:                }
                    227:        pthread_mutex_unlock(&prg->prog_mtx);
                    228: 
                    229:        return ret;
                    230: }
                    231: 
                    232: /*
1.1.2.18  misho     233:  * io_progOpen2() - Start program from pool on first unused slot
                    234:  *
                    235:  * @prg = program pool
                    236:  * return: -1 error, >-1 reside at slot
                    237:  */
                    238: int
                    239: io_progOpen2(prog_t * __restrict prg)
                    240: {
                    241: #ifdef POPEN_STREAM
                    242:        FILE *f = NULL;
                    243: #else
                    244:        int f = -1;
                    245: #endif
                    246:        int stat, ret = -1;
                    247:        register int i;
                    248:        pid_t pid;
                    249: 
                    250:        if (!prg)
                    251:                return -1;
                    252:        if (prg->prog_cnum + 1 > prg->prog_maxn) {
                    253:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    254:                return -1;
                    255:        }
                    256: 
                    257:        pthread_mutex_lock(&prg->prog_mtx);
                    258:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    259:                if (!array_Get(prg->prog_fds, i)) {
                    260:                        f = e_popen(prg->prog_name, "r+", &pid);
                    261: #ifdef POPEN_STREAM
                    262:                        if (!f) {
                    263: #else
                    264:                        if (f == -1) {
                    265: #endif
                    266:                                LOGERR;
                    267:                                break;
                    268:                        } else if (waitpid(pid, &stat, WNOHANG)) {
                    269:                                io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
                    270:                                                pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
                    271:                                e_pclose(f);
                    272:                                break;
                    273:                        } else
                    274:                                array_Set(prg->prog_fds, i, f);
                    275:                        clrbit(prg->prog_used, i);
                    276:                        prg->prog_cnum++;
                    277:                        ret = i;
                    278:                        break;
                    279:                }
                    280:        pthread_mutex_unlock(&prg->prog_mtx);
                    281: 
                    282:        return ret;
                    283: }
                    284: 
                    285: /*
1.1.2.1   misho     286:  * io_progOpen() - Execute number of program(s)
                    287:  *
                    288:  * @prg = program pool
                    289:  * @execNum = execute program(s) (0 max)
1.1.2.18  misho     290:  * return: -1 error, >0 executed programs
1.1.2.1   misho     291:  */
                    292: int
                    293: io_progOpen(prog_t * __restrict prg, u_int execNum)
                    294: {
1.1.2.11  misho     295: #ifdef POPEN_STREAM
1.1.2.1   misho     296:        FILE *f;
1.1.2.11  misho     297: #else
                    298:        int f;
                    299: #endif
1.1.2.4   misho     300:        int stat, ret = 0;
1.1.2.1   misho     301:        register int i;
1.1.2.4   misho     302:        pid_t pid;
1.1.2.1   misho     303: 
                    304:        if (!prg)
1.1.2.18  misho     305:                return -1;
1.1.2.8   misho     306:        if (prg->prog_cnum + execNum > prg->prog_maxn) {
1.1.2.1   misho     307:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
1.1.2.18  misho     308:                return -1;
1.1.2.1   misho     309:        }
                    310: 
                    311:        pthread_mutex_lock(&prg->prog_mtx);
                    312:        for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
                    313:                if (!array_Get(prg->prog_fds, i)) {
1.1.2.6   misho     314:                        f = e_popen(prg->prog_name, "r+", &pid);
1.1.2.11  misho     315: #ifdef POPEN_STREAM
1.1.2.1   misho     316:                        if (!f) {
1.1.2.11  misho     317: #else
                    318:                        if (f == -1) {
                    319: #endif
1.1.2.1   misho     320:                                LOGERR;
1.1.2.5   misho     321:                                ret = -1;
1.1.2.1   misho     322:                                break;
1.1.2.6   misho     323:                        } else if (waitpid(pid, &stat, WNOHANG)) {
                    324:                                io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
                    325:                                                pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
1.1.2.18  misho     326:                                e_pclose(f);
1.1.2.5   misho     327:                                ret = -1;
1.1.2.4   misho     328:                                break;
1.1.2.1   misho     329:                        } else
                    330:                                array_Set(prg->prog_fds, i, f);
1.1.2.15  misho     331:                        clrbit(prg->prog_used, i);
1.1.2.1   misho     332:                        prg->prog_cnum++;
                    333:                        ret++;
                    334:                }
                    335:        pthread_mutex_unlock(&prg->prog_mtx);
                    336: 
                    337:        return ret;
                    338: }
                    339: 
                    340: /*
1.1.2.8   misho     341:  * io_progGrow() - Execute to number of programs in pool
                    342:  *
                    343:  * @prg = program pool
                    344:  * @toNum = execute to number of programs (0 max)
1.1.2.17  misho     345:  * return: 0 error or nothing to do, 
                    346:  *     >0 executed programs and abs(<0) executed programs with logged error
1.1.2.8   misho     347:  */
                    348: int
                    349: io_progGrow(prog_t * __restrict prg, u_int toNum)
                    350: {
                    351:        if (!prg)
                    352:                return 0;
                    353:        if (toNum > prg->prog_maxn) {
                    354:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    355:                return 0;
                    356:        }
                    357:        if (!toNum)
                    358:                toNum = prg->prog_maxn;
1.1.2.17  misho     359:        if (toNum < prg->prog_inin)
                    360:                toNum = prg->prog_inin;
                    361: 
1.1.2.19  misho     362:        if ((int) (toNum - prg->prog_cnum) < 1)
1.1.2.17  misho     363:                return 0;
1.1.2.8   misho     364: 
                    365:        return io_progOpen(prg, toNum - prg->prog_cnum);
                    366: }
                    367: 
                    368: /*
1.1.2.1   misho     369:  * io_progVacuum() - Vacuum pool to running number of programs
                    370:  *
                    371:  * @prg = program pool
                    372:  * @toNum = vacuum to number of programs (0 to init number)
                    373:  * return: 0 error or >0 closed programs
                    374:  */
                    375: int
                    376: io_progVacuum(prog_t * __restrict prg, u_int toNum)
                    377: {
                    378:        register int i;
                    379:        int ret = 0;
1.1.2.14  misho     380:        struct tagPIOPID *p;
1.1.2.1   misho     381: 
                    382:        if (!prg)
                    383:                return 0;
                    384:        if (toNum > prg->prog_maxn) {
                    385:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                    386:                return 0;
                    387:        }
                    388:        if (!toNum)
                    389:                toNum = prg->prog_inin;
                    390: 
                    391:        pthread_mutex_lock(&prg->prog_mtx);
                    392:        for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
1.1.2.14  misho     393:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i) && 
1.1.2.11  misho     394: #ifdef POPEN_STREAM
1.1.2.14  misho     395:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
                    396:                        kill(p->pid, SIGTERM);
                    397:                        usleep(1000);
                    398:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    399:                                kill(p->pid, SIGKILL);
1.1.2.6   misho     400:                        e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11  misho     401: #else
1.1.2.14  misho     402:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
                    403:                        kill(p->pid, SIGTERM);
                    404:                        usleep(1000);
                    405:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0)
                    406:                                kill(p->pid, SIGKILL);
1.1.2.11  misho     407:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    408: #endif
1.1.2.1   misho     409:                        array_Del(prg->prog_fds, i, 0);
                    410:                        prg->prog_cnum--;
                    411:                        ret++;
                    412:                }
                    413:        pthread_mutex_unlock(&prg->prog_mtx);
                    414: 
                    415:        return ret;
                    416: }
1.1.2.7   misho     417: 
                    418: /*
                    419:  * io_progCheck() - Check exit status of program pool
                    420:  *
                    421:  * @prg = program pool
1.1.2.18  misho     422:  * @re = resurrect program to init number
1.1.2.7   misho     423:  * return: -1 error or >-1 exited programs
                    424:  */
                    425: int
1.1.2.15  misho     426: io_progCheck(prog_t * __restrict prg, int re)
1.1.2.7   misho     427: {
                    428:        int ret = 0;
                    429:        struct tagPIOPID *p;
                    430:        register int i;
                    431: 
                    432:        if (!prg)
                    433:                return -1;
                    434: 
1.1.2.9   misho     435:        pthread_mutex_lock(&prg->prog_mtx);
1.1.2.7   misho     436:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    437:                if (array_Get(prg->prog_fds, i) && 
1.1.2.11  misho     438: #ifdef POPEN_STREAM
1.1.2.22  misho     439:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*)))) {
1.1.2.11  misho     440: #else
1.1.2.22  misho     441:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t)))) {
1.1.2.11  misho     442: #endif
1.1.2.20  misho     443:                        if (waitpid(p->pid, &p->stat, WNOHANG)) {
1.1.2.9   misho     444:                                clrbit(prg->prog_used, i);
1.1.2.15  misho     445: #ifdef POPEN_STREAM
                    446:                                e_pclose(array(prg->prog_fds, i, FILE*));
                    447: #else
                    448:                                e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    449: #endif
                    450:                                array_Del(prg->prog_fds, i, 0);
                    451:                                prg->prog_cnum--;
1.1.2.7   misho     452:                                ret++;
1.1.2.9   misho     453:                        }
1.1.2.22  misho     454:                }
1.1.2.9   misho     455:        pthread_mutex_unlock(&prg->prog_mtx);
1.1.2.7   misho     456: 
1.1.2.18  misho     457:        /* resurrect to init number */
1.1.2.19  misho     458:        if (re && ((int) (prg->prog_inin - prg->prog_cnum) > 0))
1.1.2.17  misho     459:                io_progOpen(prg, prg->prog_inin - prg->prog_cnum);
1.1.2.15  misho     460: 
1.1.2.7   misho     461:        return ret;
                    462: }
1.1.2.9   misho     463: 
                    464: /*
                    465:  * io_progAttach() - Attach to open program
                    466:  *
                    467:  * @prg = program pool
1.1.2.16  misho     468:  * @newOne = Execute new one program after attach
1.1.2.9   misho     469:  * return: NULL error or !=NULL attached program handle
                    470:  */
1.1.2.11  misho     471: #ifdef POPEN_STREAM
1.1.2.9   misho     472: FILE *
1.1.2.11  misho     473: #else
                    474: int
                    475: #endif
1.1.2.16  misho     476: io_progAttach(prog_t * __restrict prg, int newOne)
1.1.2.9   misho     477: {
1.1.2.11  misho     478: #ifdef POPEN_STREAM
1.1.2.9   misho     479:        FILE *f = NULL;
1.1.2.11  misho     480: #else
                    481:        int f = -1;
                    482: #endif
1.1.2.9   misho     483:        register int i;
                    484: 
                    485:        if (!prg)
1.1.2.11  misho     486: #ifdef POPEN_STREAM
1.1.2.9   misho     487:                return NULL;
1.1.2.11  misho     488: #else
                    489:                return -1;
                    490: #endif
1.1.2.9   misho     491: 
                    492:        pthread_mutex_lock(&prg->prog_mtx);
                    493:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    494:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
                    495:                        setbit(prg->prog_used, i);
1.1.2.11  misho     496: #ifdef POPEN_STREAM
1.1.2.9   misho     497:                        f = array(prg->prog_fds, i, FILE*);
1.1.2.11  misho     498: #else
                    499:                        f = array(prg->prog_fds, i, intptr_t);
                    500: #endif
1.1.2.9   misho     501:                        break;
                    502:                }
                    503:        pthread_mutex_unlock(&prg->prog_mtx);
                    504: 
1.1.2.20  misho     505:        /* execute new one program */
                    506:        if (newOne) {
                    507:                if (f)
                    508:                        io_progOpen(prg, 1);
                    509:                else if ((i = io_progOpen2(prg)) > -1)
                    510:                        /* not found free program */
1.1.2.18  misho     511: #ifdef POPEN_STREAM
1.1.2.20  misho     512:                        f = array(prg->prog_fds, i, FILE*);
1.1.2.18  misho     513: #else
1.1.2.20  misho     514:                        f = array(prg->prog_fds, i, intptr_t);
1.1.2.18  misho     515: #endif
                    516:        }
                    517: 
1.1.2.9   misho     518:        return f;
                    519: }
                    520: 
                    521: /*
                    522:  * io_progDetach() - Detch from open program
                    523:  *
                    524:  * @prg= program pool
                    525:  * @pfd = attached program handle
                    526:  * return: none
                    527:  */
                    528: void
1.1.2.11  misho     529: #ifdef POPEN_STREAM
1.1.2.9   misho     530: io_progDetach(prog_t * __restrict prg, FILE *pfd)
1.1.2.11  misho     531: #else
                    532: io_progDetach(prog_t * __restrict prg, int pfd)
                    533: #endif
1.1.2.9   misho     534: {
                    535:        register int i;
                    536: 
                    537:        if (!prg || !pfd)
                    538:                return;
                    539: 
                    540:        pthread_mutex_lock(&prg->prog_mtx);
                    541:        for (i = 0; i < array_Size(prg->prog_fds); i++)
1.1.2.11  misho     542: #ifdef POPEN_STREAM
1.1.2.9   misho     543:                if (array(prg->prog_fds, i, FILE*) == pfd) {
1.1.2.11  misho     544: #else
                    545:                if (array(prg->prog_fds, i, intptr_t) == pfd) {
                    546: #endif
1.1.2.9   misho     547:                        clrbit(prg->prog_used, i);
                    548:                        break;
                    549:                }
                    550:        pthread_mutex_unlock(&prg->prog_mtx);
                    551: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>