blob: ec9306062b98a5c21a123be8c7b4fa52eaff2e36 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fw_dunit.hpp"
#include <mutex>
#include <util/concurrent/spinlock_mutex.hpp>
#include <ace/Task.h>
#include <ace/Time_Value.h>
#include <ace/Guard_T.h>
namespace { // NOLINT(google-build-namespaces)
using apache::geode::util::concurrent::spinlock_mutex;
DUNIT_TASK(s1p1, Basic)
{
spinlock_mutex s;
{ std::lock_guard<spinlock_mutex> lk(s); }
}
END_TASK(Basic)
perf::Semaphore *triggerA;
perf::Semaphore *triggerB;
perf::Semaphore *triggerM;
spinlock_mutex lock;
ACE_Time_Value *btime;
class ThreadA : public ACE_Task_Base {
public:
ThreadA() : ACE_Task_Base() {}
int svc() {
{
std::lock_guard<spinlock_mutex> lk(lock);
LOG("ThreadA: Acquired lock x.");
triggerM->release();
triggerA->acquire();
}
LOG("ThreadA: Released lock.");
return 0;
}
};
class ThreadB : public ACE_Task_Base {
public:
ThreadB() : ACE_Task_Base() {}
int svc() {
triggerB->acquire();
{
std::lock_guard<spinlock_mutex> lk(lock);
btime = new ACE_Time_Value(ACE_OS::gettimeofday());
LOG("ThreadB: Acquired lock.");
triggerM->release();
}
return 0;
}
};
DUNIT_TASK(s1p1, TwoThreads)
{
triggerA = new perf::Semaphore(0);
triggerB = new perf::Semaphore(0);
triggerM = new perf::Semaphore(0);
ThreadA *threadA = new ThreadA();
ThreadB *threadB = new ThreadB();
threadA->activate();
threadB->activate();
// A runs, locks the spinlock, and triggers me. B is idle.
triggerM->acquire();
// A is now idle, but holds lock. Tell B to acquire the lock
ACE_Time_Value stime = ACE_OS::gettimeofday();
triggerB->release();
SLEEP(5000);
// B will be stuck until we tell A to release it.
triggerA->release();
// wait until B tells us it has acquired the lock.
triggerM->acquire();
// Now diff btime (when B acquired the lock) and stime to see that it
// took longer than the 5000 seconds before A released it.
ACE_Time_Value delta = *btime - stime;
char msg[1024];
sprintf(msg, "acquire delay was %lu\n", delta.msec());
LOG(msg);
ASSERT(delta.msec() >= 4900, "Expected 5 second or more spinlock delay");
// Note the test is against 4900 instead of 5000 as there are some
// measurement
// issues. Often delta comes back as 4999 on linux.
threadA->wait();
delete threadA;
threadB->wait();
delete threadB;
}
END_TASK(TwoThreads)
} // namespace