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; }
void ssl_DestroyCipherSpecs(PRCList *list) { while (!PR_CLIST_IS_EMPTY(list)) { ssl3CipherSpec *spec = (ssl3CipherSpec *)PR_LIST_TAIL(list); ssl_FreeCipherSpec(spec); } }
void ssl3_DestroyRemoteExtensions(PRCList *list) { PRCList *cur_p; while (!PR_CLIST_IS_EMPTY(list)) { cur_p = PR_LIST_TAIL(list); PR_REMOVE_LINK(cur_p); PORT_Free(cur_p); } }
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); } }
bundleCacheEntry_t * nsStringBundleService::insertIntoCache(nsIStringBundle* aBundle, nsCStringKey* aHashKey) { bundleCacheEntry_t *cacheEntry; if (mBundleMap.Count() < MAX_CACHED_BUNDLES) { // cache not full - create a new entry void *cacheEntryArena; PL_ARENA_ALLOCATE(cacheEntryArena, &mCacheEntryPool, sizeof(bundleCacheEntry_t)); cacheEntry = (bundleCacheEntry_t*)cacheEntryArena; } else { // cache is full // take the last entry in the list, and recycle it. cacheEntry = (bundleCacheEntry_t*)PR_LIST_TAIL(&mBundleCache); // remove it from the hash table and linked list NS_ASSERTION(mBundleMap.Exists(cacheEntry->mHashKey), "Element will not be removed!"); #ifdef DEBUG_alecf NS_WARNING(nsPrintfCString(300, "Booting %s to make room for %s\n", cacheEntry->mHashKey->GetString(), aHashKey->GetString()).get()); #endif mBundleMap.Remove(cacheEntry->mHashKey); PR_REMOVE_LINK((PRCList*)cacheEntry); // free up excess memory recycleEntry(cacheEntry); } // at this point we have a new cacheEntry that doesn't exist // in the hashtable, so set up the cacheEntry cacheEntry->mBundle = aBundle; NS_ADDREF(cacheEntry->mBundle); cacheEntry->mHashKey = (nsCStringKey*)aHashKey->Clone(); // insert the entry into the cache and map, make it the MRU mBundleMap.Put(cacheEntry->mHashKey, cacheEntry); return cacheEntry; }
NSAPI_PUBLIC ACLAttrGetter_t * ACL_AttrGetterNext(ACLAttrGetterList_t *getters, ACLAttrGetter_t *last) { ACLAttrGetter_t *head; ACLAttrGetter_t *next = 0; if (getters && *getters && last) { head = (ACLAttrGetter_t *)(*getters); if (head) { /* End of list? */ if (last != (ACLAttrGetter_t *)PR_LIST_TAIL(&head->list)) { /* No, get next entry */ next = (ACLAttrGetter_t *)PR_NEXT_LINK(&last->list); } } } return next; }
nsPreflightCache::CacheEntry* nsPreflightCache::GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal, PRBool aWithCredentials, PRBool aCreate) { nsCString key; if (!GetCacheKey(aURI, aPrincipal, aWithCredentials, key)) { NS_WARNING("Invalid cache key!"); return nsnull; } CacheEntry* entry; if (mTable.Get(key, &entry)) { // Entry already existed so just return it. Also update the LRU list. // Move to the head of the list. PR_REMOVE_LINK(entry); PR_INSERT_LINK(entry, &mList); return entry; } if (!aCreate) { return nsnull; } // This is a new entry, allocate and insert into the table now so that any // failures don't cause items to be removed from a full cache. entry = new CacheEntry(key); if (!entry) { NS_WARNING("Failed to allocate new cache entry!"); return nsnull; } NS_ASSERTION(mTable.Count() <= PREFLIGHT_CACHE_SIZE, "Something is borked, too many entries in the cache!"); // Now enforce the max count. if (mTable.Count() == PREFLIGHT_CACHE_SIZE) { // Try to kick out all the expired entries. PRTime now = PR_Now(); mTable.Enumerate(RemoveExpiredEntries, &now); // If that didn't remove anything then kick out the least recently used // entry. if (mTable.Count() == PREFLIGHT_CACHE_SIZE) { CacheEntry* lruEntry = static_cast<CacheEntry*>(PR_LIST_TAIL(&mList)); PR_REMOVE_LINK(lruEntry); // This will delete 'lruEntry'. mTable.Remove(lruEntry->mKey); NS_ASSERTION(mTable.Count() == PREFLIGHT_CACHE_SIZE - 1, "Somehow tried to remove an entry that was never added!"); } } if (!mTable.Put(key, entry)) { // Failed, clean up the new entry. delete entry; NS_WARNING("Failed to add entry to the CORS preflight cache!"); return nsnull; } PR_INSERT_LINK(entry, &mList); return entry; }
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; }
static void _NSFC_DestroyEntry(NSFCCache cip, NSFCEntryImpl *nep, PRBool delCntIt) { NSFCEntryImpl **list; PRUint32 bucket = nep->hash % cip->hsize; int found = 0; PR_ASSERT(nep->refcnt == 0); PR_ASSERT(nep->fDelete); PR_ASSERT(nep->fHashed); ++nep->seqno; /* First remove the name entry from the hname hash table. */ NSFC_ASSERTBUCKETHELD(cip, bucket); for (list = &cip->hname[bucket]; *list; list = &(*list)->next) { if (*list == nep) { *list = nep->next; found = 1; break; } } PR_ASSERT(found == 1); nep->fHashed = 0; if (delCntIt == PR_TRUE) { PR_ASSERT(cip->busydCnt > 0); PR_AtomicDecrement((PRInt32 *)&cip->busydCnt); } /* No one but us should be able to see this entry */ PR_ASSERT(nep->fDelete == PR_TRUE); PR_ASSERT(nep->fHashed == PR_FALSE); PR_ASSERT(nep->refcnt == 0); PR_ASSERT(PR_LIST_HEAD(&nep->hit_list) == PR_LIST_TAIL(&nep->hit_list)); /* Free cached content */ if (nep->flags & NSFCENTRY_HASCONTENT) { NSFC_MD_FreeContent(cip, nep); } /* Handle notifications for any associated private data */ NSFCPrivateData *pdenext; NSFCPrivateData *pde; for (pde = nep->pdlist; pde; pde = pdenext) { pdenext = pde->next; if (pde->key->delfn) { pde->key->delfn(cip, nep->filename, pde->key, pde->pdata); } NSFC_Free(pde, sizeof(*pde), cip); } /* Destroy private data lock */ if (nep->pdLock) { PR_DestroyLock(nep->pdLock); nep->pdLock = NULL; } /* Free filename string from entry, if any */ if (nep->filename) { NSFC_FreeStr(nep->filename, cip); nep->filename = NULL; } /* Return the file name entry to the free list */ PR_Lock(cip->namefLock); nep->next = cip->namefl; cip->namefl = nep; PR_Unlock(cip->namefLock); /* Finally decrement the number of entries used */ if (!PR_AtomicDecrement((PRInt32*)&cip->curFiles)) { /* Wake anyone waiting for this final entry to go away */ NSFC_RELEASEBUCKET(cip, bucket); NSFC_EnterCacheMonitor(cip); NSFC_ExitCacheMonitor(cip); NSFC_ACQUIREBUCKET(cip, bucket); } /* Cache contents have been modified */ cip->sig++; }
static NSFCStatus _NSFC_DeleteEntry(NSFCCache cache, NSFCEntryImpl *nep, PRBool hasBucketLock, PRBool delCntIt, PRBool outdCntIt) { NSFCStatus rfc = NSFC_OK; PR_ASSERT(nep); /* Get access to nep's bucket if caller doesn't have it already */ PRUint32 bucket; if (hasBucketLock == PR_FALSE) { if (nep->fDelete) { return rfc; } bucket = nep->hash % cache->hsize; NSFC_ACQUIREBUCKET(cache, bucket); } else { NSFC_ASSERTBUCKETHELD(cache, nep->hash % cache->hsize); } /* If nep hasn't already been marked for deletion... */ if (!nep->fDelete) { /* Remove nep from the hit list */ PR_Lock(cache->hitLock); PR_REMOVE_AND_INIT_LINK(&nep->hit_list); PR_Unlock(cache->hitLock); PR_ASSERT(PR_LIST_HEAD(&nep->hit_list) == PR_LIST_TAIL(&nep->hit_list)); /* Mark it for delete */ nep->fDelete = 1; /* Increment total count of entries deleted */ if (delCntIt == PR_TRUE) { PR_AtomicIncrement((PRInt32 *)&cache->delCnt); PR_AtomicIncrement((PRInt32 *)&cache->busydCnt); if (outdCntIt == PR_TRUE) PR_AtomicIncrement((PRInt32 *)&cache->outdCnt); } } if (nep->refcnt == 0) { /* * Given that the entry's use count is zero, the caller had better have * the bucket lock (because he clearly doesn't have a refcnt) */ PR_ASSERT(hasBucketLock == PR_TRUE); _NSFC_DestroyEntry(cache, nep, delCntIt); } /* Release the bucket lock if we weren't holding it on entry */ if (hasBucketLock == PR_FALSE) { NSFC_RELEASEBUCKET(cache, bucket); } /* Cache contents have been modified */ cache->sig++; return rfc; }