es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Por qué no es necesario que múltiples hilos compartan un bloqueo para llamar a mmap, como lo hacen con malloc/calloc/sbrk?

Estoy trabajando con ptmalloc y algo interesante que me encontré es que cuando una arena se queda sin fragmentos disponibles (y el fragmento superior no es lo suficientemente grande), tiene que extender la arena usando sbrk() o asignar una región no contigua usando mmap(). Lo que me llamó la atención en particular es que, para asignar más memoria usando sbrk(), se debe adquirir un bloqueo antes de poder llamar a esta función (además del bloqueo obtenido previamente para tener posesión exclusiva de la arena actual). Sin embargo, no es necesario adquirir ningún bloqueo antes de llamar a mmap(). A continuación, se incluyen las partes específicas de la función sys_alloc() del archivo malloc.c incluido en la implementación de ptmalloc (para referencia):

  • Llamada para extender la arena usando sbrk():
if (HAVE_MORECORE && tbase == CMFAIL) { // Intentar MORECORE no contiguo
  size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
  if (asize < HALF_MAX_SIZE_T) {
    char* br = CMFAIL;
    char* end = CMFAIL;
    ACQUIRE_MORECORE_LOCK(); // BLOQUEO
    br = (char*)(CALL_MORECORE(asize));
    end = (char*)(CALL_MORECORE(0));
    RELEASE_MORECORE_LOCK();  // DESBLOQUEO
    if (br != CMFAIL && end != CMFAIL && br < end) {
      size_t ssize = end - br;
      if (ssize > nb + TOP_FOOT_SIZE) {
        tbase = br;
        tsize = ssize;
      }
    }
  }
}
  • Llamada para extender la arena usando mmap():
if (HAVE_MMAP && tbase == CMFAIL) { // Intentar MMAP
  size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
  size_t rsize = granularity_align(req);
  if (rsize > nb) { // Fallar si envuelve alrededor de cero
    char* mp = (char*)(CALL_MMAP(rsize));
    if (mp != CMFAIL) {
      tbase = mp;
      tsize = rsize;
      mmap_flag = IS_MMAPPED_BIT;
    }
  }
}

Cualquier ayuda para entender por qué esto puede funcionar incluso con múltiples hilos que tienen el mismo patrón de memoria (y, por lo tanto, tienen que extender sus arenas al mismo tiempo) sin tener que usar bloqueos (es decir, cómo mmap() garantiza devolver direcciones distintas, incluso si se llama simultáneamente con una dirección sugerida NULL) sería muy apreciada.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Explicación de la asignación de memoria en ptmalloc

    En la implementación de ptmalloc, cuando un área se queda sin espacio disponible, debe extender el área utilizando sbrk() o asignar una región no contigua utilizando mmap(). Lo interesante es que, al extender el área utilizando sbrk(), la implementación adquiere un bloqueo antes de llamarlo, pero no es necesario adquirir un bloqueo antes de llamar a mmap().

    Esto se debe a que la asignación realizada utilizando sbrk() se realiza en memoria contigua, lo que significa que el nuevo espacio se agrega al espacio existente. Para evitar condiciones de carrera donde varios hilos intentan extender el mismo espacio al mismo tiempo, se adquiere un bloqueo para asegurarse de que solo un hilo esté modificando el montón en un momento dado.

    Por otro lado, mmap() asigna memoria desde el espacio de direcciones virtuales del sistema operativo, que no es contigua con el espacio existente. Por lo tanto, se garantiza que múltiples llamadas simultáneas a mmap() desde diferentes hilos devuelvan direcciones distintas. Por lo tanto, no se requiere un bloqueo para asignar regiones no contiguas utilizando mmap().

    Esto significa que en un entorno de múltiples hilos, mmap() es una forma más eficiente de asignar memoria, ya que se puede hacer de forma concurrente sin causar contención en un bloqueo.

Comments are closed.