       }
 
       if (!NewSlot) {
-        // Allocate at least the default size.
-        // TODO: generalize this for workers which need a larger data slot
-        // i.e. using DS_Worker_Warp_Slot_Size.
-        if (DS_Slot_Size > DataSize)
-          NewSize = DS_Slot_Size;
+        // Allocate at least the default size for each type of slot.
+        size_t DefaultSlotSize =
+            IsMasterThread() ? DS_Slot_Size : DS_Worker_Warp_Slot_Size;
+        if (DefaultSlotSize > NewSize)
+          NewSize = DefaultSlotSize;
         NewSlot = (__kmpc_data_sharing_slot *)malloc(
             sizeof(__kmpc_data_sharing_slot) + NewSize);
         NewSlot->Next = 0;

      // Reset stack pointer to the requested address.
      StackP = (void *)RequestedEndAddress;
    }

    return FrameP;
  }

  // TODO: add memory fence here when this function can be called by
  // worker threads also. For now, this function is only called by the
  // master thread of each team.

  // TODO: implement sharing across workers.
  return 0;
}

// Pop the stack and free any memory which can be reclaimed.

// reclaim all outstanding global memory slots since it is
// likely we have reached the end of the kernel.
EXTERN void __kmpc_data_sharing_pop_stack(void *FrameStart) {
  if (IsWarpMasterActiveThread()) {
    unsigned WID = getWarpId();

    __kmpc_data_sharing_slot *&SlotP = DataSharingState.SlotPtr[WID];
    void *&StackP = DataSharingState.StackPtr[WID];

    // Pop current frame from slot.
    StackP = FrameStart;

    // If we try to pop the last frame of the current slot we need to
    // move to the previous slot if there is one.
