If malloc() sleeps, Giant is dropped. Recheck for another thread

doing our work.

Remove unneeded check for failed M_WAITOK allocation.

Reviewed by:	alc
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2015-02-18 18:12:06 +00:00
parent cf9b923f48
commit 1395226703

View File

@ -358,9 +358,22 @@ kern_shmat(td, shmid, shmaddr, shmflg)
if (shmmap_s == NULL) {
shmmap_s = malloc(shminfo.shmseg * sizeof(struct shmmap_state),
M_SHM, M_WAITOK);
for (i = 0; i < shminfo.shmseg; i++)
shmmap_s[i].shmid = -1;
p->p_vmspace->vm_shm = shmmap_s;
/*
* If malloc() above sleeps, the Giant lock is
* temporarily dropped, which allows another thread to
* allocate shmmap_state and set vm_shm. Recheck
* vm_shm and free the new shmmap_state if another one
* is already allocated.
*/
if (p->p_vmspace->vm_shm != NULL) {
free(shmmap_s, M_SHM);
shmmap_s = p->p_vmspace->vm_shm;
} else {
for (i = 0; i < shminfo.shmseg; i++)
shmmap_s[i].shmid = -1;
p->p_vmspace->vm_shm = shmmap_s;
}
}
shmseg = shm_find_segment_by_shmid(shmid);
if (shmseg == NULL) {
@ -826,8 +839,6 @@ shmrealloc(void)
return;
newsegs = malloc(shminfo.shmmni * sizeof(*newsegs), M_SHM, M_WAITOK);
if (newsegs == NULL)
return;
for (i = 0; i < shmalloced; i++)
bcopy(&shmsegs[i], &newsegs[i], sizeof(newsegs[0]));
for (; i < shminfo.shmmni; i++) {