Exemplo n.º 1
0
static TimerEvent *CreateTimer(
    PRIntervalTime timeout,
    void (*func)(void *),
    void *arg)
{
    TimerEvent *timer;
    PRCList *links, *tail;
    TimerEvent *elem;

    timer = PR_NEW(TimerEvent);
    if (NULL == timer)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return timer;
    }
    timer->absolute = PR_IntervalNow() + timeout;
    timer->func = func;
    timer->arg = arg;
    timer->ref_count = 2;
    PR_Lock(tm_vars.ml);
    tail = links = PR_LIST_TAIL(&tm_vars.timer_queue);
    while (links->prev != tail)
    {
        elem = TIMER_EVENT_PTR(links);
        if ((PRInt32)(timer->absolute - elem->absolute) >= 0)
        {
            break;
        }
        links = links->prev;
    }
    PR_INSERT_AFTER(&timer->links, links);
    PR_NotifyCondVar(tm_vars.new_timer);
    PR_Unlock(tm_vars.ml);
    return timer;
}
NSFC_RecordEntryHit(NSFCCache cache, NSFCEntry entry)
{
    PR_ASSERT(entry->refcnt >= 1);

    entry->hitcnt++;

    /*
     * If existing entries can be recycled for new files, indicate that
     * this entry is active.
     */
    if (cache->cfg.replaceFiles == PR_TRUE) {
        /* Update the hit list order if this entry is in the hit list */
        PR_Lock(cache->hitLock);
        if (PR_LIST_HEAD(&entry->hit_list) != PR_LIST_TAIL(&entry->hit_list)) {
            if (cache->cfg.hitOrder == PR_TRUE) {
                /*
                 * If this entry is not at the head of the hit list,
                 * move it ahead of all entries with the same hitcnt.
                 */
                PRCList *prev;
                NSFCEntryImpl *pnep;

                for (prev = PR_PREV_LINK(&entry->hit_list);
                     prev != &cache->hit_list;
                     prev = PR_PREV_LINK(prev)) {

                    pnep = NSFCENTRYIMPL(prev);
                    if (pnep->hitcnt > entry->hitcnt) {
                        break; /* Our spot in the list */
                    }
                }

                /* Move the element up if necessary */
                if (prev != PR_PREV_LINK(&entry->hit_list)) {
                    PR_REMOVE_LINK(&entry->hit_list);
                    PR_INSERT_AFTER(&entry->hit_list, prev);
                }
            }
            else {
                /* Ignore hitcnt, keep list in strict MRU to LRU order */
                if (&entry->hit_list != PR_LIST_HEAD(&cache->hit_list)) {
                    PR_REMOVE_LINK(&entry->hit_list);
                    PR_INSERT_LINK(&entry->hit_list, &cache->hit_list);
                }
            }
        }
        PR_Unlock(cache->hitLock);
    }
}
Exemplo n.º 3
0
PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout,
							PRJobFn fn, void * arg, PRBool joinable)
{
	PRIntervalTime now;
	PRJob *jobp;

	if (PR_INTERVAL_NO_TIMEOUT == timeout) {
		PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
		return NULL;
	}
	if (PR_INTERVAL_NO_WAIT == timeout) {
		/*
		 * no waiting; add to jobq right away
		 */
		return(PR_QueueJob(tpool, fn, arg, joinable));
	}
	jobp = alloc_job(joinable, tpool);
	if (NULL == jobp) {
		return NULL;
	}

	/*
	 * Add a new job to timer_jobq
	 * wakeup timer worker thread
	 */

	jobp->job_func = fn;
	jobp->job_arg = arg;
	jobp->tpool = tpool;
	jobp->timeout = timeout;

	now = PR_IntervalNow();
	jobp->absolute = now + timeout;


	PR_Lock(tpool->timerq.lock);
	jobp->on_timerq = PR_TRUE;
	if (PR_CLIST_IS_EMPTY(&tpool->timerq.list))
		PR_APPEND_LINK(&jobp->links,&tpool->timerq.list);
	else {
		PRCList *qp;
		PRJob *tmp_jobp;
		/*
		 * insert into the sorted timer jobq
		 */
		for (qp = tpool->timerq.list.prev; qp != &tpool->timerq.list;
							qp = qp->prev) {
			tmp_jobp = JOB_LINKS_PTR(qp);
			if ((PRInt32)(jobp->absolute - tmp_jobp->absolute) >= 0) {
				break;
			}
		}
		PR_INSERT_AFTER(&jobp->links,qp);
	}
	tpool->timerq.cnt++;
	/*
	 * notify timer worker thread(s)
	 */
	notify_timerq(tpool);
	PR_Unlock(tpool->timerq.lock);
	return jobp;
}
Exemplo n.º 4
0
/* queue a job, when a socket is readable or writeable */
static PRJob *
queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg,
				PRBool joinable, io_op_type op)
{
	PRJob *jobp;
	PRIntervalTime now;

	jobp = alloc_job(joinable, tpool);
	if (NULL == jobp) {
		return NULL;
	}

	/*
	 * Add a new job to io_jobq
	 * wakeup io worker thread
	 */

	jobp->job_func = fn;
	jobp->job_arg = arg;
	jobp->tpool = tpool;
	jobp->iod = iod;
	if (JOB_IO_READ == op) {
		jobp->io_op = JOB_IO_READ;
		jobp->io_poll_flags = PR_POLL_READ;
	} else if (JOB_IO_WRITE == op) {
		jobp->io_op = JOB_IO_WRITE;
		jobp->io_poll_flags = PR_POLL_WRITE;
	} else if (JOB_IO_ACCEPT == op) {
		jobp->io_op = JOB_IO_ACCEPT;
		jobp->io_poll_flags = PR_POLL_READ;
	} else if (JOB_IO_CONNECT == op) {
		jobp->io_op = JOB_IO_CONNECT;
		jobp->io_poll_flags = PR_POLL_WRITE|PR_POLL_EXCEPT;
	} else {
		delete_job(jobp);
		PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
		return NULL;
	}

	jobp->timeout = iod->timeout;
	if ((PR_INTERVAL_NO_TIMEOUT == iod->timeout) ||
			(PR_INTERVAL_NO_WAIT == iod->timeout)) {
		jobp->absolute = iod->timeout;
	} else {
		now = PR_IntervalNow();
		jobp->absolute = now + iod->timeout;
	}


	PR_Lock(tpool->ioq.lock);

	if (PR_CLIST_IS_EMPTY(&tpool->ioq.list) ||
			(PR_INTERVAL_NO_TIMEOUT == iod->timeout)) {
		PR_APPEND_LINK(&jobp->links,&tpool->ioq.list);
	} else if (PR_INTERVAL_NO_WAIT == iod->timeout) {
		PR_INSERT_LINK(&jobp->links,&tpool->ioq.list);
	} else {
		PRCList *qp;
		PRJob *tmp_jobp;
		/*
		 * insert into the timeout-sorted ioq
		 */
		for (qp = tpool->ioq.list.prev; qp != &tpool->ioq.list;
							qp = qp->prev) {
			tmp_jobp = JOB_LINKS_PTR(qp);
			if ((PRInt32)(jobp->absolute - tmp_jobp->absolute) >= 0) {
				break;
			}
		}
		PR_INSERT_AFTER(&jobp->links,qp);
	}

	jobp->on_ioq = PR_TRUE;
	tpool->ioq.cnt++;
	/*
	 * notify io worker thread(s)
	 */
	PR_Unlock(tpool->ioq.lock);
	notify_ioq(tpool);
	return jobp;
}
NSFC_NewFilenameEntry(NSFCCache cip, const char *filename, 
                      PRUint32 hvalue, NSFCStatus &rfc)
{
    PRUint32 bucket = hvalue % cip->hsize;

    PR_ASSERT(cip);

    if (cip->state != NSFCCache_Active) {
        rfc = NSFC_DEADCACHE;
        return NULL;
    }

    rfc = NSFC_OK;

    /* Replace file cache entries once the cache fills up */
    if (_NSFC_IsTimeToReplace(cip)) {
        PR_Lock(cip->hitLock);
        if (!PR_CLIST_IS_EMPTY(&cip->hit_list)) {
            NSFCEntryImpl* nepDelete;
            PRUint32 bucketDelete;

            /* Get the LRU entry from the hit list and remember its bucket */
            PRCList *lru = PR_LIST_TAIL(&cip->hit_list);
            PR_ASSERT(lru);
            nepDelete = (NSFCEntryImpl*)((char*)lru - offsetof(NSFCEntryImpl,
                                                               hit_list));
            bucketDelete = nepDelete->hash % cip->hsize;
            PR_Unlock(cip->hitLock);

            /* Get access to the LRU entry's bucket */
            if (bucket != bucketDelete) {
                NSFC_RELEASEBUCKET(cip, bucket);
                NSFC_ACQUIREBUCKET(cip, bucketDelete);
            }

            /* Look for the LRU entry in the bucket */
            NSFCEntryImpl *nep;
            for (nep = cip->hname[bucketDelete]; nep; nep = nep->next) {
                if (nep == nepDelete) break;
            }
            if (nep == nepDelete) {
                /* The LRU entry is still around, mark it for deletion */
                NSFC_DeleteEntry(cip, nep, PR_TRUE);

                /* Increment count of replaced entries */
                PR_AtomicIncrement((PRInt32*)&cip->rplcCnt);
            }

            /* Get access to the new entry's bucket */
            if (bucket != bucketDelete) {
                NSFC_RELEASEBUCKET(cip, bucketDelete);
                NSFC_ACQUIREBUCKET(cip, bucket);
            }
        }
        else {
            PR_Unlock(cip->hitLock);
        }
    }

    /* Respect limit on number of cache entries */
    if (cip->curFiles >= cip->cfg.maxFiles) {
        cip->cacheFull = PR_TRUE;
        rfc = NSFC_NOSPACE;
        return NULL;
    }

    /* Get a file name entry */
    PR_Lock(cip->namefLock);
    NSFCEntryImpl *nep = cip->namefl;
    if (nep != NULL) {
        /* Found a file name entry on the free list */
        PR_ASSERT(nep->refcnt == 0);
        PR_ASSERT(!nep->fHashed);
        cip->namefl = nep->next;
    }
    PR_Unlock(cip->namefLock);
    if (nep == NULL) {
        /* Allocate a new file name entry */
        nep = (NSFCEntryImpl *)NSFC_Calloc(1, sizeof(*nep), cip);
        if (nep) {
            nep->seqno = 1;
        }
    }

    if (nep) {
        nep->filename = NSFC_Strdup(filename, cip);
        if (nep->filename) {
            /* Initialize entry */
            nep->next = NULL;
            nep->pdLock = PR_NewLock();
            nep->pdlist = NULL;
            nep->finfo.pr.type = PR_FILE_OTHER;
            nep->finfo.pr.size = 0;
            nep->finfo.pr.creationTime = 0;
            nep->finfo.pr.modifyTime = 0;
            PRIntervalTime now = ft_timeIntervalNow();
            nep->finfo.lastUpdate = now;
            nep->finfo.fileid[0] = hvalue;
            nep->finfo.fileid[1] = nep->seqno;
            nep->finfo.prerr = 0;
            nep->finfo.oserr = 0;
            nep->hash = hvalue;
            nep->hitcnt = 0;
            nep->refcnt = 1;
            nep->flags = 0;
            nep->fHashed = 1;
            nep->fDelete = 0;
            nep->fWriting = 0;

            /* Add entry to cache instance hash table */
            NSFC_ASSERTBUCKETHELD(cip, bucket);
            nep->next = cip->hname[bucket];
            cip->hname[bucket] = nep;
            PR_AtomicIncrement((PRInt32*)&cip->curFiles);

            /* Add entry to the hit list */
            PR_Lock(cip->hitLock);
            PR_INIT_CLIST(&nep->hit_list);
            if (cip->cfg.hitOrder == PR_TRUE) {
                /*
                 * Add this entry towards the end of the hit list,
                 * but ahead of other entries with a zero hit count.
                 */
                PRCList *prev;
                NSFCEntryImpl *pnep;

                for (prev = PR_LIST_TAIL(&cip->hit_list);
                     prev != &cip->hit_list;
                     prev = PR_PREV_LINK(prev)) {

                    pnep = NSFCENTRYIMPL(prev);
                    if (pnep->hitcnt > nep->hitcnt) {
                        break; /* Our spot in the list */
                    }
                }

                PR_INSERT_AFTER(&nep->hit_list, prev);
            }
            else {
                /* Put new entry at head of hit list */
                PR_INSERT_LINK(&nep->hit_list, &cip->hit_list);
            }
            PR_Unlock(cip->hitLock);

            PR_ASSERT(!nep->fDelete);
        }
        else {
            /* Failed, so return the entry to the free list */
            PR_Lock(cip->namefLock);
            nep->next = cip->namefl;
            cip->namefl = nep;
            nep = NULL;
            PR_Unlock(cip->namefLock);

            cip->cacheFull = PR_TRUE; /* file cache is full */
            rfc = NSFC_NOSPACE;
        }
    }
    else {
        cip->cacheFull = PR_TRUE; /* file cache is full */
        rfc = NSFC_NOSPACE;
    }

    /* Cache contents have been modified */
    cip->sig++;

    return nep;
}