Puzzled by ESP32 timers and mutex

I've verified that what you said is correct by adding some code to loop() to check if millis() changes in the critical section:

void loop() {
  static uint32_t totalCount = 0;
  portENTER_CRITICAL(&timerMux); // Ensure loop() and onTimer() don't access shared data at the same time
    uint32_t onTimerCountSample1 = onTimerCount;
    uint32_t millisSample1 = millis();
    delay(100); // To make sure onTimer() is called whilst mutex is locked.
    uint32_t millisSample2 = millis();
    Serial.print("onTimerCount ");
    if(onTimerCount == onTimerCountSample1){
      Serial.print("didn't change ");
    }
    else{
      Serial.print("changed by ");
      Serial.print(onTimerCount-onTimerCountSample1);
    }
    Serial.print(" : millis() ");

    if(millisSample1 == millisSample2){
      Serial.print("didn't change ");
    }
    else{
      Serial.print("changed by ");
      Serial.print(millisSample2-millisSample1);
    }
    Serial.println(" in loop's critical section");
    totalCount+= onTimerCount;
    onTimerCount = 0;
  portEXIT_CRITICAL(&timerMux); // onTimer() can now access shared data
  Serial.print("totalCount = ");
  Serial.println(totalCount);
  delay(900); // To make total delay ~1 second
}

Serial monitor output:

onTimerCount didn't change  : millis() didn't change  in loop's critical section
totalCount = 0
onTimerCount didn't change  : millis() didn't change  in loop's critical section
totalCount = 1000
onTimerCount didn't change  : millis() didn't change  in loop's critical section
totalCount = 2000
onTimerCount didn't change  : millis() didn't change  in loop's critical section
totalCount = 3000

This topic, post#2 says delay() just returns if interrupts are off.