Is it possible to solve the critical section problem with an atomic subtract operation?
If the number of threads is less than the number of values that you can hold in a memory location, then you can implement a non-overflowing test-and-test-and-set operation with atomic-fetch-and-decrement.

So, for example, if you have 32-bit integers and less than 4 billion threads the following should work:

initialize: x = 0

acquireLock:
  repeat:
    while x != 0:
      # do nothing
    tmp = atomicFetchAndDecrement(x) # (decrements x and returns *new* value of x)
  until tmp == -1

releaseLock:
  x = 0


Each thread only decrements the counter once for each time that it sees the counter get reset to 0, so the value of x never becomes smaller than -numberOfThreads.

The real value of fetch-and-increment is that you can make critical sections that are "fair" in the sense that threads are given the lock in the order in which they first request it.  Like this:

initialize: nextTicket = 0; current = 0

acquireLock:
  myTicket = atomicFetchAndDecrement(nextTicket)       # (decrements and then returns *new* value)
  myTicket = myTicket + 1                # make up for the weird atomicFetchAndDecrement semantics
  while current != myTicket:
    # do nothing

releaseLock:
  current = current - 1                  # does not need to be atomic, releaser is only writer


Again, with 32-bit integers this works as long as the number of threads is less than $2^{32}$.