Explorar el Código

[MERGE #4492 @obastemur] Fixes an issue with flaky 262 test

Merge pull request #4492 from obastemur:262_stuff

fixes #4405
obastemur hace 8 años
padre
commit
09034518ef

+ 4 - 6
bin/ch/262.js

@@ -3,8 +3,7 @@
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
-LR"====(
-
+R"====(
 var $262 = {
   createRealm: function () {
     return WScript.LoadScript('', 'samethread').$262;
@@ -12,7 +11,7 @@ var $262 = {
   global: this,
   agent: {
     start: function (src) {
-      WScript.LoadScript(        
+      WScript.LoadScript(
         `
         $262 = {
           agent:{
@@ -28,6 +27,5 @@ var $262 = {
     sleep: function (timeout) { WScript.Sleep(timeout); },
     getReport: function () { return WScript.GetReport(); },
   },
-}
-
-)===="
+};
+)===="

+ 1 - 1
bin/ch/HostConfigFlagsList.h

@@ -14,6 +14,6 @@ FLAG(bool, EnsureCloseJITServer,            "JIT process will be force closed wh
 FLAG(bool, IgnoreScriptErrorCode,           "Don't return error code on script error", false)
 FLAG(bool, MuteHostErrorMsg,                "Mute host error output, e.g. module load failures", false)
 FLAG(bool, TraceHostCallback,               "Output traces for host callbacks", false)
-FLAG(bool, $262,                            "load $262 harness", false)
+FLAG(bool, Test262,                         "load Test262 harness", false)
 #undef FLAG
 #endif

+ 0 - 17
bin/ch/RuntimeThreadData.cpp

@@ -4,22 +4,6 @@
 //-------------------------------------------------------------------------------------------------------
 #include "stdafx.h"
 
-#ifndef _WIN32
-HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName)
-{
-    // xplat-todo: implement this in PAL
-    Assert(false);
-    return INVALID_HANDLE_VALUE;
-}
-BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount)
-{
-    // xplat-todo: implement this in PAL
-    Assert(false);
-    return FALSE;
-}
-
-#endif
-
 void RuntimeThreadLocalData::Initialize(RuntimeThreadData* threadData)
 {
     this->threadData = threadData;
@@ -29,7 +13,6 @@ void RuntimeThreadLocalData::Uninitialize()
 {
 }
 
-
 THREAD_LOCAL RuntimeThreadLocalData threadLocalData;
 
 RuntimeThreadLocalData& GetRuntimeThreadLocalData()

+ 12 - 11
bin/ch/WScriptJsrt.cpp

@@ -938,7 +938,10 @@ bool WScriptJsrt::Initialize()
 
     IfJsrtErrorFail(InitializeModuleCallbacks(), false);
 
-    if (HostConfigFlags::flags.$262)
+    // When the command-line argument `-Test262` is set,
+    // WScript will have the extra support API below and $262 will be
+    // added to global scope
+    if (HostConfigFlags::flags.Test262)
     {
         IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Broadcast", BroadcastCallback));
         IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "ReceiveBroadcast", ReceiveBroadcastCallback));
@@ -947,19 +950,17 @@ bool WScriptJsrt::Initialize()
         IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Leaving", LeavingCallback));
         IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Sleep", SleepCallback));
 
-
-        // OSX does build does not support $262 as filename
-        const wchar_t $262[] =
+        // $262
+        const char Test262[] =
             #include "262.js"
-            ;
+        ;
 
-        JsValueRef $262ScriptRef;
-        IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateStringUtf16((uint16_t*)$262, _countof($262) - 1, &$262ScriptRef));
+        JsValueRef Test262ScriptRef;
+        IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString(Test262, strlen(Test262), &Test262ScriptRef));
 
         JsValueRef fname;
-        IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString("$262", strlen("$262"), &fname));
-        IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsRun($262ScriptRef, WScriptJsrt::GetNextSourceContext(), fname, JsParseScriptAttributeNone, nullptr));
-
+        IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString("262", strlen("262"), &fname));
+        IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsRun(Test262ScriptRef, WScriptJsrt::GetNextSourceContext(), fname, JsParseScriptAttributeNone, nullptr));
     }
 
 Error:
@@ -1534,7 +1535,7 @@ HRESULT WScriptJsrt::ModuleMessage::Call(LPCSTR fileName)
                     specifierFullPath = moduleDirEntry->second;
                 }
             }
-            
+
             specifierFullPath += *specifierStr;
             if (_fullpath(fullPath, specifierFullPath.c_str(), _MAX_PATH) == nullptr)
             {

+ 1 - 0
pal/src/CMakeLists.txt

@@ -158,6 +158,7 @@ set(SOURCES
   shmemory/shmemory.cpp
   synchobj/event.cpp
   synchobj/mutex.cpp
+  synchobj/semaphore.cpp
   synchmgr/synchcontrollers.cpp
   synchmgr/synchmanager.cpp
   synchmgr/wait.cpp

+ 60 - 0
pal/src/include/pal/semaphore.hpp

@@ -0,0 +1,60 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*++
+
+
+
+Module Name:
+
+    semaphore.hpp
+
+Abstract:
+
+    Semaphore object structure definition.
+
+
+
+--*/
+
+#ifndef _PAL_SEMAPHORE_H_
+#define _PAL_SEMAPHORE_H_
+
+#include "corunix.hpp"
+
+namespace CorUnix
+{
+    extern CObjectType otSemaphore;
+
+    typedef struct
+    {
+        LONG lMaximumCount;
+    } SemaphoreImmutableData;
+
+    PAL_ERROR
+    InternalCreateSemaphore(
+        CPalThread *pThread,
+        LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
+        LONG lInitialCount,
+        LONG lMaximumCount,
+        LPCWSTR lpName,
+        HANDLE *phSemaphore
+        );
+
+    PAL_ERROR
+    InternalReleaseSemaphore(
+        CPalThread *pThread,
+        HANDLE hSemaphore,
+        LONG lReleaseCount,
+        LPLONG lpPreviousCount
+        );
+
+}
+
+#endif //_PAL_SEMAPHORE_H_

+ 604 - 0
pal/src/synchobj/semaphore.cpp

@@ -0,0 +1,604 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*++
+
+
+
+Module Name:
+
+    semaphore.cpp
+
+Abstract:
+
+    Implementation of the sempahore synchroniztion object as described in
+    the WIN32 API
+
+Revision History:
+
+
+
+--*/
+
+#include "pal/semaphore.hpp"
+#include "pal/thread.hpp"
+#include "pal/dbgmsg.h"
+
+using namespace CorUnix;
+
+/* ------------------- Definitions ------------------------------*/
+SET_DEFAULT_DEBUG_CHANNEL(SYNC);
+
+CObjectType CorUnix::otSemaphore(
+                otiSemaphore,
+                NULL,   // No cleanup routine
+                NULL,   // No initialization routine
+                sizeof(SemaphoreImmutableData),
+                // NULL,   // No immutable data copy routine
+                // NULL,   // No immutable data cleanup routine
+                0,      // No process local data
+                // NULL,   // No process local data cleanup routine
+                0,      // No shared data
+                0,      // Should be SEMAPHORE_ALL_ACCESS; currently ignored (no Win32 security)
+                CObjectType::SecuritySupported,
+                CObjectType::SecurityInfoNotPersisted,
+                CObjectType::UnnamedObject,
+                CObjectType::LocalDuplicationOnly,
+                CObjectType::WaitableObject,
+                CObjectType::ObjectCanBeUnsignaled,
+                CObjectType::ThreadReleaseAltersSignalCount,
+                CObjectType::NoOwner
+                );
+
+CAllowedObjectTypes aotSempahore(otiSemaphore);
+
+/*++
+Function:
+CreateSemaphoreExA
+
+Note:
+lpSemaphoreAttributes currently ignored:
+-- Win32 object security not supported
+-- handles to semaphore objects are not inheritable
+
+Parameters:
+See MSDN doc.
+--*/
+
+HANDLE
+PALAPI
+CreateSemaphoreExA(
+        IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
+        IN LONG lInitialCount,
+        IN LONG lMaximumCount,
+        IN LPCSTR lpName,
+        IN /*_Reserved_*/  DWORD dwFlags,
+        IN DWORD dwDesiredAccess)
+{
+    // dwFlags is reserved and unused, and dwDesiredAccess is currently
+    // only ever used as SEMAPHORE_ALL_ACCESS.  The other parameters
+    // all map to CreateSemaphoreA.
+    _ASSERTE(SEMAPHORE_ALL_ACCESS == dwDesiredAccess);
+
+    return CreateSemaphoreA(
+        lpSemaphoreAttributes,
+        lInitialCount,
+        lMaximumCount,
+        lpName);
+}
+
+/*++
+Function:
+  CreateSemaphoreA
+
+Note:
+  lpSemaphoreAttributes currently ignored:
+  -- Win32 object security not supported
+  -- handles to semaphore objects are not inheritable
+
+Parameters:
+  See MSDN doc.
+--*/
+
+HANDLE
+PALAPI
+CreateSemaphoreA(
+         IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
+         IN LONG lInitialCount,
+         IN LONG lMaximumCount,
+         IN LPCSTR lpName)
+{
+    HANDLE hSemaphore = NULL;
+    CPalThread *pthr = NULL;
+    PAL_ERROR palError;
+
+    PERF_ENTRY(CreateSemaphoreA);
+    ENTRY("CreateSemaphoreA(lpSemaphoreAttributes=%p, lInitialCount=%d, "
+          "lMaximumCount=%d, lpName=%p (%s))\n",
+          lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName, lpName?lpName:"NULL");
+
+    pthr = InternalGetCurrentThread();
+
+    if (lpName != nullptr)
+    {
+        ASSERT("lpName: Cross-process named objects are not supported in PAL");
+        palError = ERROR_NOT_SUPPORTED;
+    }
+    else
+    {
+        palError = InternalCreateSemaphore(
+            pthr,
+            lpSemaphoreAttributes,
+            lInitialCount,
+            lMaximumCount,
+            NULL,
+            &hSemaphore
+            );
+    }
+
+    //
+    // We always need to set last error, even on success:
+    // we need to protect ourselves from the situation
+    // where last error is set to ERROR_ALREADY_EXISTS on
+    // entry to the function
+    //
+
+    pthr->SetLastError(palError);
+
+    LOGEXIT("CreateSemaphoreA returns HANDLE %p\n", hSemaphore);
+    PERF_EXIT(CreateSemaphoreA);
+    return hSemaphore;
+}
+
+/*++
+Function:
+CreateSemaphoreExW
+
+Note:
+lpSemaphoreAttributes currentely ignored:
+-- Win32 object security not supported
+-- handles to semaphore objects are not inheritable
+
+Parameters:
+See MSDN doc.
+--*/
+
+HANDLE
+PALAPI
+CreateSemaphoreExW(
+        IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
+        IN LONG lInitialCount,
+        IN LONG lMaximumCount,
+        IN LPCWSTR lpName,
+        IN /*_Reserved_*/  DWORD dwFlags,
+        IN DWORD dwDesiredAccess)
+{
+    // dwFlags is reserved and unused
+
+    return CreateSemaphoreW(
+        lpSemaphoreAttributes,
+        lInitialCount,
+        lMaximumCount,
+        lpName);
+}
+
+/*++
+Function:
+  CreateSemaphoreW
+
+Note:
+  lpSemaphoreAttributes currentely ignored:
+  -- Win32 object security not supported
+  -- handles to semaphore objects are not inheritable
+
+Parameters:
+  See MSDN doc.
+--*/
+
+HANDLE
+PALAPI
+CreateSemaphoreW(
+         IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
+         IN LONG lInitialCount,
+         IN LONG lMaximumCount,
+         IN LPCWSTR lpName)
+{
+    HANDLE hSemaphore = NULL;
+    PAL_ERROR palError;
+    CPalThread *pthr = NULL;
+
+    PERF_ENTRY(CreateSemaphoreW);
+    ENTRY("CreateSemaphoreW(lpSemaphoreAttributes=%p, lInitialCount=%d, "
+          "lMaximumCount=%d, lpName=%p (%S))\n",
+          lpSemaphoreAttributes, lInitialCount, lMaximumCount,
+          lpName, lpName?lpName:W16_NULLSTRING);
+
+    pthr = InternalGetCurrentThread();
+
+    palError = InternalCreateSemaphore(
+        pthr,
+        lpSemaphoreAttributes,
+        lInitialCount,
+        lMaximumCount,
+        lpName,
+        &hSemaphore
+        );
+
+    //
+    // We always need to set last error, even on success:
+    // we need to protect ourselves from the situation
+    // where last error is set to ERROR_ALREADY_EXISTS on
+    // entry to the function
+    //
+
+    pthr->SetLastError(palError);
+
+    LOGEXIT("CreateSemaphoreW returns HANDLE %p\n", hSemaphore);
+    PERF_EXIT(CreateSemaphoreW);
+    return hSemaphore;
+}
+
+/*++
+Function:
+  InternalCreateSemaphore
+
+Note:
+  lpSemaphoreAttributes currentely ignored:
+  -- Win32 object security not supported
+  -- handles to semaphore objects are not inheritable
+
+Parameters
+  pthr -- thread data for calling thread
+  phEvent -- on success, receives the allocated semaphore handle
+
+  See MSDN docs on CreateSemaphore for all other parameters.
+--*/
+
+PAL_ERROR
+CorUnix::InternalCreateSemaphore(
+    CPalThread *pthr,
+    LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
+    LONG lInitialCount,
+    LONG lMaximumCount,
+    LPCWSTR lpName,
+    HANDLE *phSemaphore
+    )
+{
+    CObjectAttributes oa(lpName, lpSemaphoreAttributes);
+    PAL_ERROR palError = NO_ERROR;
+    IPalObject *pobjSemaphore = NULL;
+    IPalObject *pobjRegisteredSemaphore = NULL;
+    SemaphoreImmutableData *pSemaphoreData;
+
+    _ASSERTE(NULL != pthr);
+    _ASSERTE(NULL != phSemaphore);
+
+    ENTRY("InternalCreateSemaphore(pthr=%p, lpSemaphoreAttributes=%p, "
+        "lInitialCount=%d, lMaximumCount=%d, lpName=%p, phSemaphore=%p)\n",
+        pthr,
+        lpSemaphoreAttributes,
+        lInitialCount,
+        lMaximumCount,
+        lpName,
+        phSemaphore
+        );
+
+    if (lpName != nullptr)
+    {
+        ASSERT("lpName: Cross-process named objects are not supported in PAL");
+        palError = ERROR_NOT_SUPPORTED;
+        goto InternalCreateSemaphoreExit;
+    }
+
+    if (lMaximumCount <= 0)
+    {
+        ERROR("lMaximumCount is invalid (%d)\n", lMaximumCount);
+        palError = ERROR_INVALID_PARAMETER;
+        goto InternalCreateSemaphoreExit;
+    }
+
+    if ((lInitialCount < 0) || (lInitialCount > lMaximumCount))
+    {
+        ERROR("lInitialCount is invalid (%d)\n", lInitialCount);
+        palError = ERROR_INVALID_PARAMETER;
+        goto InternalCreateSemaphoreExit;
+    }
+
+    palError = g_pObjectManager->AllocateObject(
+        pthr,
+        &otSemaphore,
+        &oa,
+        &pobjSemaphore
+        );
+
+    if (NO_ERROR != palError)
+    {
+        goto InternalCreateSemaphoreExit;
+    }
+
+    palError = pobjSemaphore->GetImmutableData(reinterpret_cast<void**>(&pSemaphoreData));
+
+    if (NO_ERROR != palError)
+    {
+        ASSERT("Error %d obtaining object data\n", palError);
+        goto InternalCreateSemaphoreExit;
+    }
+
+    pSemaphoreData->lMaximumCount = lMaximumCount;
+
+    if (0 != lInitialCount)
+    {
+        ISynchStateController *pssc;
+
+        palError = pobjSemaphore->GetSynchStateController(
+            pthr,
+            &pssc
+            );
+
+        if (NO_ERROR == palError)
+        {
+            palError = pssc->SetSignalCount(lInitialCount);
+            pssc->ReleaseController();
+        }
+
+        if (NO_ERROR != palError)
+        {
+            ASSERT("Unable to set new semaphore state (%d)\n", palError);
+            goto InternalCreateSemaphoreExit;
+        }
+    }
+
+    palError = g_pObjectManager->RegisterObject(
+        pthr,
+        pobjSemaphore,
+        &aotSempahore,
+        0, // Should be SEMAPHORE_ALL_ACCESS; currently ignored (no Win32 security)
+        phSemaphore,
+        &pobjRegisteredSemaphore
+        );
+
+    //
+    // pobjSemaphore is invalidated by the call to RegisterObject, so NULL it
+    // out here to ensure that we don't try to release a reference on
+    // it down the line.
+    //
+
+    pobjSemaphore = NULL;
+
+InternalCreateSemaphoreExit:
+
+    if (NULL != pobjSemaphore)
+    {
+        pobjSemaphore->ReleaseReference(pthr);
+    }
+
+    if (NULL != pobjRegisteredSemaphore)
+    {
+        pobjRegisteredSemaphore->ReleaseReference(pthr);
+    }
+
+    LOGEXIT("InternalCreateSemaphore returns %d\n", palError);
+
+    return palError;
+}
+
+
+/*++
+Function:
+  ReleaseSemaphore
+
+Parameters:
+  See MSDN doc.
+--*/
+
+BOOL
+PALAPI
+ReleaseSemaphore(
+         IN HANDLE hSemaphore,
+         IN LONG lReleaseCount,
+         OUT LPLONG lpPreviousCount)
+{
+    PAL_ERROR palError = NO_ERROR;
+    CPalThread *pthr = NULL;
+
+    PERF_ENTRY(ReleaseSemaphore);
+    ENTRY("ReleaseSemaphore(hSemaphore=%p, lReleaseCount=%d, "
+          "lpPreviousCount=%p)\n",
+          hSemaphore, lReleaseCount, lpPreviousCount);
+
+    pthr = InternalGetCurrentThread();
+
+    palError = InternalReleaseSemaphore(
+        pthr,
+        hSemaphore,
+        lReleaseCount,
+        lpPreviousCount
+        );
+
+    if (NO_ERROR != palError)
+    {
+        pthr->SetLastError(palError);
+    }
+
+    LOGEXIT ("ReleaseSemaphore returns BOOL %d\n", (NO_ERROR == palError));
+    PERF_EXIT(ReleaseSemaphore);
+    return (NO_ERROR == palError);
+}
+
+/*++
+Function:
+  InternalReleaseSemaphore
+
+Parameters:
+  pthr -- thread data for calling thread
+
+  See MSDN docs on ReleaseSemaphore for all other parameters
+--*/
+
+PAL_ERROR
+CorUnix::InternalReleaseSemaphore(
+    CPalThread *pthr,
+    HANDLE hSemaphore,
+    LONG lReleaseCount,
+    LPLONG lpPreviousCount
+    )
+{
+    PAL_ERROR palError = NO_ERROR;
+    IPalObject *pobjSemaphore = NULL;
+    ISynchStateController *pssc = NULL;
+    SemaphoreImmutableData *pSemaphoreData;
+    LONG lOldCount;
+
+    _ASSERTE(NULL != pthr);
+
+    ENTRY("InternalReleaseSempahore(pthr=%p, hSemaphore=%p, lReleaseCount=%d, "
+        "lpPreviousCount=%p)\n",
+        pthr,
+        hSemaphore,
+        lReleaseCount,
+        lpPreviousCount
+        );
+
+    if (0 >= lReleaseCount)
+    {
+        palError = ERROR_INVALID_PARAMETER;
+        goto InternalReleaseSemaphoreExit;
+    }
+
+    palError = g_pObjectManager->ReferenceObjectByHandle(
+        pthr,
+        hSemaphore,
+        &aotSempahore,
+        0, // Should be SEMAPHORE_MODIFY_STATE; currently ignored (no Win32 security)
+        &pobjSemaphore
+        );
+
+    if (NO_ERROR != palError)
+    {
+        ERROR("Unable to obtain object for handle %p (error %d)!\n", hSemaphore, palError);
+        goto InternalReleaseSemaphoreExit;
+    }
+
+    palError = pobjSemaphore->GetImmutableData(reinterpret_cast<void**>(&pSemaphoreData));
+
+    if (NO_ERROR != palError)
+    {
+        ASSERT("Error %d obtaining object data\n", palError);
+        goto InternalReleaseSemaphoreExit;
+    }
+
+    palError = pobjSemaphore->GetSynchStateController(
+        pthr,
+        &pssc
+        );
+
+    if (NO_ERROR != palError)
+    {
+        ASSERT("Error %d obtaining synch state controller\n", palError);
+        goto InternalReleaseSemaphoreExit;
+    }
+
+    palError = pssc->GetSignalCount(&lOldCount);
+
+    if (NO_ERROR != palError)
+    {
+        ASSERT("Error %d obtaining current signal count\n", palError);
+        goto InternalReleaseSemaphoreExit;
+    }
+
+    _ASSERTE(lOldCount <= pSemaphoreData->lMaximumCount);
+    if (lReleaseCount > pSemaphoreData->lMaximumCount - lOldCount)
+    {
+        palError = ERROR_INVALID_PARAMETER;
+        goto InternalReleaseSemaphoreExit;
+    }
+
+    palError = pssc->IncrementSignalCount(lReleaseCount);
+
+    if (NO_ERROR != palError)
+    {
+        ASSERT("Error %d incrementing signal count\n", palError);
+        goto InternalReleaseSemaphoreExit;
+    }
+
+    if (NULL != lpPreviousCount)
+    {
+        *lpPreviousCount = lOldCount;
+    }
+
+InternalReleaseSemaphoreExit:
+
+    if (NULL != pssc)
+    {
+        pssc->ReleaseController();
+    }
+
+    if (NULL != pobjSemaphore)
+    {
+        pobjSemaphore->ReleaseReference(pthr);
+    }
+
+    LOGEXIT("InternalReleaseSemaphore returns %d\n", palError);
+
+    return palError;
+}
+
+// TODO: Implementation of OpenSemaphoreA() doesn't exist, do we need it? More generally, do we need the A versions at all?
+
+/*++
+Function:
+  OpenSemaphoreW
+
+Note:
+  dwDesiredAccess is currently ignored (no Win32 object security support)
+  bInheritHandle is currently ignored (handles to semaphore are not inheritable)
+
+Parameters:
+  See MSDN doc.
+--*/
+
+HANDLE
+PALAPI
+OpenSemaphoreW(
+       IN DWORD dwDesiredAccess,
+       IN BOOL bInheritHandle,
+       IN LPCWSTR lpName)
+{
+    HANDLE hSemaphore = NULL;
+    PAL_ERROR palError = NO_ERROR;
+    CPalThread *pthr = NULL;
+
+    PERF_ENTRY(OpenSemaphoreW);
+    ENTRY("OpenSemaphoreW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S))\n",
+          dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:W16_NULLSTRING);
+
+    pthr = InternalGetCurrentThread();
+
+    /* validate parameters */
+    if (lpName == nullptr)
+    {
+        ERROR("lpName is NULL\n");
+        palError = ERROR_INVALID_PARAMETER;
+    }
+    else
+    {
+        ASSERT("lpName: Cross-process named objects are not supported in PAL");
+        palError = ERROR_NOT_SUPPORTED;
+    }
+
+    if (NO_ERROR != palError)
+    {
+        pthr->SetLastError(palError);
+    }
+
+    LOGEXIT("OpenSemaphoreW returns HANDLE %p\n", hSemaphore);
+    PERF_EXIT(OpenSemaphoreW);
+
+    return hSemaphore;
+}

+ 21 - 15
test/$262/$262test.js → test/262/262test.js

@@ -1,3 +1,8 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
 "use strict";
 var $ = {  global: this,  createRealm(options) {    options = options || {};    options.globals = options.globals || {};    var realm = WScript.LoadScript(this.source, 'samethread');    realm.$.source = this.source;    realm.$.destroy = function () {      if (options.destroy) {        options.destroy();      }    };    for(var glob in options.globals) {      realm.$.global[glob] = options.globals[glob];    }    return realm.$;  },  evalScript(code) {    try {      WScript.LoadScript(code);      return { type: 'normal', value: undefined };    } catch (e) {      return { type: 'throw', value: e };    }  },  getGlobal(name) {    return this.global[name];  },  setGlobal(name, value) {    this.global[name] = value;  },  destroy() { /* noop */ },  source: "var $ = {  global: this,  createRealm(options) {    options = options || {};    options.globals = options.globals || {};    var realm = WScript.LoadScript(this.source, 'samethread');    realm.$.source = this.source;    realm.$.destroy = function () {      if (options.destroy) {        options.destroy();      }    };    for(var glob in options.globals) {      realm.$.global[glob] = options.globals[glob];    }    return realm.$;  },  evalScript(code) {    try {      WScript.LoadScript(code);      return { type: 'normal', value: undefined };    } catch (e) {      return { type: 'throw', value: e };    }  },  getGlobal(name) {    return this.global[name];  },  setGlobal(name, value) {    this.global[name] = value;  },  destroy() { /* noop */ },  source: \"\"};"};function Test262Error(message) {
     if (message) this.message = message;
@@ -21,7 +26,7 @@ function $DONE(err) {
   if (err) {
     $ERROR(err);
   }
-  print('pass');
+  print('PASS');
   $.destroy();
 }
 
@@ -29,7 +34,6 @@ function $LOG(str) {
   print(str);
 }
 
-
 function assert(mustBeTrue, message) {
   if (mustBeTrue === true) {
     return;
@@ -124,31 +128,35 @@ assert.throws.early = function(err, code) {
 // them go into a wait, thus controlling the waiting order.  Then we wake them
 // one by one and observe the wakeup order.
 
-for ( var i=0 ; i < 3 ; i++ ) {
+for (var i = 0; i < 3; i++) {
 $262.agent.start(
 `
 $262.agent.receiveBroadcast(function (sab) {
   var ia = new Int32Array(sab);
-  while (Atomics.load(ia, ${i+1}) == 0);
-  $262.agent.report(${i} + Atomics.wait(ia, 0, 0));
+
+  while (Atomics.load(ia, ${i}) == 0);
+
+  // the one below should produce 'not-equal'.
+  // because ia[i] is no longer 0! (see the loop above)
+  // otherwise it would wait until timeout
+  $262.agent.report(${i} + Atomics.wait(ia, ${i}, 0));
   $262.agent.leaving();
 })
 `);
 }
 
-var ia = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT*4));
+var ia = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 3));
 $262.agent.broadcast(ia.buffer);
 
-// Make them sleep in order 0 1 2 on ia[0]
-for ( var i=0 ; i < 3 ; i++ ) {
-  Atomics.store(ia, i+1, 1);
+// the `while` loop above waits until we store a value below
+for (var i = 0; i < 3; i++) {
+  Atomics.store(ia, i, 1);
   $262.agent.sleep(500);
 }
 
-// Wake them up one at a time and check the order is 0 1 2
-for ( var i=0 ; i < 3 ; i++ ) {
-  assert.sameValue(Atomics.wake(ia, 0, 1), 1);
-  assert.sameValue(getReport(), i + "ok");
+for (var i = 0; i < 3; i++) {
+  assert.sameValue(Atomics.load(ia, i), 1);
+  assert.sameValue(getReport(), i + "not-equal");
 }
 
 function getReport() {
@@ -158,7 +166,5 @@ function getReport() {
     return r;
 }
 
-
-
 ;$DONE();
 ;$.destroy();

+ 2 - 3
test/$262/rlexe.xml → test/262/rlexe.xml

@@ -2,9 +2,8 @@
 <regress-exe>
   <test>
     <default>
-      <compile-flags>-$262</compile-flags>
-      <tags>exclude_xplat</tags>
-      <files>$262test.js</files>
+      <compile-flags>-Test262</compile-flags>
+      <files>262test.js</files>
     </default>
   </test>
 </regress-exe>

+ 1 - 1
test/rlexedirs.xml

@@ -7,7 +7,7 @@
 </dir>
 <dir>
   <default>
-    <files>$262</files>
+    <files>262</files>
   </default>
 </dir>
 <dir>