init_op_threads()
{
    pthread_condattr_t condAttr;
    int32_t max_threads = config_get_threadnumber();
    int32_t rc;
    int32_t *threads_indexes;

    /* Initialize the locks and cv */
    if ((rc = pthread_mutex_init(&work_q_lock, NULL)) != 0) {
        slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                      "Cannot create new lock.  error %d (%s)\n",
                      rc, strerror(rc));
        exit(-1);
    }
    if ((rc = pthread_condattr_init(&condAttr)) != 0) {
        slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                      "Cannot create new condition attribute variable.  error %d (%s)\n",
                      rc, strerror(rc));
        exit(-1);
    } else if ((rc = pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC)) != 0) {
        slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                      "Cannot set condition attr clock.  error %d (%s)\n",
                      rc, strerror(rc));
        exit(-1);
    } else if ((rc = pthread_cond_init(&work_q_cv, &condAttr)) != 0) {
        slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                      "Cannot create new condition variable.  error %d (%s)\n",
                      rc, strerror(rc));
        exit(-1);
    }
    pthread_condattr_destroy(&condAttr); /* no longer needed */

    work_q_stack = PR_CreateStack("connection_work_q");
    op_stack = PR_CreateStack("connection_operation");
    alloc_per_thread_snmp_vars(max_threads);
    init_thread_private_snmp_vars();
    

    threads_indexes = (int32_t *) slapi_ch_calloc(max_threads, sizeof(int32_t));
    for (size_t i = 0; i < max_threads; i++) {
        threads_indexes[i] = i + 1; /* idx 0 is reserved for global snmp_vars */
    }
    
    /* start the operation threads */
    for (size_t i = 0; i < max_threads; i++) {
        PR_SetConcurrency(4);
        if (PR_CreateThread(PR_USER_THREAD,
                            (VFP)(void *)connection_threadmain, (void *) &threads_indexes[i],
                            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
                            PR_UNJOINABLE_THREAD,
                            SLAPD_DEFAULT_THREAD_STACKSIZE) == NULL) {
            int prerr = PR_GetError();
            slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                          "PR_CreateThread failed, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
                          prerr, slapd_pr_strerror(prerr));
        } else {
            g_incr_active_threadcnt();
        }
    }
    /* Here we should free thread_indexes, but because of the dynamic of the new
     * threads (connection_threadmain) we are not sure when it can be freed.
     * Let's accept that unique initialization leak (typically 32 to 64 bytes)
     */
}
init_op_threads()
{
    pthread_condattr_t condAttr;
    int32_t max_threads = config_get_threadnumber();
    int32_t rc;
    int32_t *threads_indexes;

     
    if ((rc = pthread_mutex_init(&work_q_lock, NULL)) != 0) {
        slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                      "Cannot create new lock.  error %d (%s)\n",
                      rc, strerror(rc));
        exit(-1);
    }
    if ((rc = pthread_condattr_init(&condAttr)) != 0) {
        slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                      "Cannot create new condition attribute variable.  error %d (%s)\n",
                      rc, strerror(rc));
        exit(-1);
    } else if ((rc = pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC)) != 0) {
        slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                      "Cannot set condition attr clock.  error %d (%s)\n",
                      rc, strerror(rc));
        exit(-1);
    } else if ((rc = pthread_cond_init(&work_q_cv, &condAttr)) != 0) {
        slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                      "Cannot create new condition variable.  error %d (%s)\n",
                      rc, strerror(rc));
        exit(-1);
    }
    pthread_condattr_destroy(&condAttr);  

    work_q_stack = PR_CreateStack("connection_work_q");
    op_stack = PR_CreateStack("connection_operation");
    alloc_per_thread_snmp_vars(max_threads);
    init_thread_private_snmp_vars();
    

    threads_indexes = (int32_t *) slapi_ch_calloc(max_threads, sizeof(int32_t));
    for (size_t i = 0; i < max_threads; i++) {
        threads_indexes[i] = i + 1;  
    }
    
     
    for (size_t i = 0; i < max_threads; i++) {
        PR_SetConcurrency(4);
        if (PR_CreateThread(PR_USER_THREAD,
                            (VFP)(void *)connection_threadmain, (void *) &threads_indexes[i],
                            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
                            PR_UNJOINABLE_THREAD,
                            SLAPD_DEFAULT_THREAD_STACKSIZE) == NULL) {
            int prerr = PR_GetError();
            slapi_log_err(SLAPI_LOG_ERR, "init_op_threads",
                          "PR_CreateThread failed, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
                          prerr, slapd_pr_strerror(prerr));
        } else {
            g_incr_active_threadcnt();
        }
    }
     
}