How do you use SetThreadAffinityMask with QueryPerformanceFrequency? - windows

I have a long standing program with the FAA that was running great until the FAA started deploying Dell GX-760 desktops. The program is a graphical replay of air traffic. I use the QueryPerformanceFrequency function to get the processor counter. With the GX 760 it appears to not be processor dependent. I found this http://msdn.microsoft.com/en-us/library/ms644904(VS.85).aspx which descibes what I am seeing.
On a multiprocessor computer, it
should not matter which processor is
called. However, youit can get
different results on different
processors due to bugs in the basic
input/output system (BIOS) or the
hardware abstraction layer (HAL). To
specify processor affinity for a
thread, use the SetThreadAffinityMask
function.
I not familiar with SetThreadAffinityMask, how does this work and how should I implement it? Here is my code that gets the count.
Thanks,
Dave
'Declarations
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
'I set the Frequency on Startup
cTime.SetFrequency
Public Sub SetFrequency()
'Get the Processor Frequency. This is locked at Windows startup and does n
Dim f As Currency
QueryPerformanceFrequency f
cTime.Frequency = f
End Sub
When the program needs the time it calls
Public Function CurrentCount() As Currency
'What is the current processoer count
QueryPerformanceCounter CurrentCount 'get current count number
End Function

It isn't exactly clear what kind of problem you are having. It is very unlikely that the quoted MSDN article is relevant, a Dell Optiplex 760 doesn't have multiple processors. Just one with multiple cores, it is not subject to this kind of bug. You can easily test this by running your program with the start.exe, it allows setting the processor affinity:
start /affinity 1 yourapp.exe
Perhaps more relevant is that newer machines take shortcuts on the frequency source, using whatever source happens to be available in the chipset. They typically have a much higher return value for QueryPerformanceFrequency. Two billion isn't unusual, maybe that screws up your math. Working with 'currency' instead of a true 64-bit integer is rather toe-curling.
Also check the BIOS revision for your machine, they had rather a large number of them, all the way up to A08.

Related

What is the difference between GetActiveProcessorCount and GetMaximumProcessorCount?

Windows 7 added the functions GetActiveProcessorCount and GetMaximumProcessorCount, but MSDN doesn't say much about them. As far as I can tell, both functions always return the same value, which is the number of logical CPUs in the specified processor group or the system as a whole. So what makes a processor "active" or "inactive"?

getting system time in Vxworks

is there anyways to get the system time in VxWorks besides tickGet() and tickAnnounce? I want to measure the time between the task switches of a specified task but I think the precision of tickGet() is not good enough because the the two tickGet() values at the beggining and the end of taskSwitchHookAdd function is always the same!
If you are looking to try and time task switches, I would assume you need a timer at least at the microsecond (us) level.
Usually, timers/clocks this fine grained are only provided by the platform you are running on. If you are working on an embedded system, you can try and read thru the manuals for your board support package (if there is one) to see if there are any functions provided to access various timers on a board.
A more low level solution would be to figure out the processor that is running on your system and then write some simple assembly code to poll the processor's internal timebase register (TBR). This might require a bit of research on the processor you are running on, but could be easily done.
If you are running on a PPC based processor, you can use the code below to read the TBR:
loop: mftbu rx #load most significant half from TBU
mftbl ry #load least significant half from TBL
mftbu rz #load from TBU again
cmpw rz,rx #see if 'old' = 'new'
bne loop #repeat if two values read from TBU are unequal
On an x86 based processor, you might consider using the RDTSC assembly instruction to read the Time Stamp Counter (TSC). On vxWorks, pentiumALib has some library functions (pentiumTscGet64() and pentiumTscGet32()) that will make reading the TSC easier using C.
source: http://www-inteng.fnal.gov/Integrated_Eng/GoodwinDocs/pdf/Sys%20docs/PowerPC/PowerPC%20Elapsed%20Time.pdf
Good luck!
It depends on what platform you are on, but if it is x86 then you can use:
pentiumTscGet64();

How can I get a pulse in win32 Assembler (specifically nasm)?

I'm planning on making a clock. An actual clock, not something for Windows. However, I would like to be able to write most of the code now. I'll be using a PIC16F628A to drive the clock, and it has a timer I can access (actually, it has 3, in addition to the clock it has built in). Windows, however, does not appear to have this function. Which makes making a clock a bit hard, since I need to know how long it's been so I can update the current time. So I need to know how I can get a pulse (1Hz, 1KHz, doesn't really matter as long as I know how fast it is) in Windows.
There are many timer objects available in Windows. Probably the easiest to use for your purposes would be the Multimedia Timer, but that's been deprecated. It would still work, but Microsoft recommends using one of the new timer types.
I'd recommend using a threadpool timer if you know your application will be running under Windows Vista, Server 2008, or later. If you have to support Windows XP, use a Timer Queue timer.
There's a lot to those APIs, but general use is pretty simple. I showed how to use them (in C#) in my article Using the Windows Timer Queue API. The code is mostly API calls, so I figure you won't have trouble understanding and converting it.
The LARGE_INTEGER is just an 8-byte block of memory that's split into a high part and a low part. In assembly, you can define it as:
MyLargeInt equ $
MyLargeIntLow dd 0
MyLargeIntHigh dd 0
If you're looking to learn ASM, just do a Google search for [x86 assembly language tutorial]. That'll get you a whole lot of good information.
You could use a waitable timer object. Since Windows is not a real-time OS, you'll need to make sure you set the period long enough that you won't miss pulses. A tenth of a second should be safe most of the time.
Additional:
The const LARGE_INTEGER you need to pass to SetWaitableTimer is easy to implement in NASM, it's just an eight byte constant:
period: dq 100 ; 100ms = ten times a second
Pass the address of period as the second argument to SetWaitableTimer.

what is the size of windows semaphore object?

How to find size of a semaphore object in windows?
I tried using sizeof() but we cannot give name of the sempahore object as an argument to sizeof. It has to be the handle. sizeof(HANDLE) gives us the size of handle and not semaphore.
This what is known as an "opaque handle.". There is no way to know how big it really is, what it contains or how any of the functions work internally. This gives Microsoft the ability to completely rewrite the implementation with each new version of Windows if they want to without worrying about breaking existing code. It's a similar concept to having a public and private interface to a class. Since we are not working on the Windows kernel, we only get to see the public interface.
Update:
It might be possible to get a rough idea of how big they are by creating a bunch and monitoring what happens to your memory usage in Process Explorer. However, since there is a good chance that they live in the kernel and not in user space, it might not show up at all. In any case, there are no guarantees about any other version of Windows, past or future, including patches/service packs.
It's something "hidden" from you. You can't say how big it is. And it's a kernel object, so it probably doesn't even live in your address space. It's like asking "how big is the Process Table?", or "how many MB is Windows wasting?".
I'll add that I have made a small test on my Windows 7 32 bits machine: 100000 kernel semaphores (with name X{number} with 0 <= number < 100000)) : 4 mb of kernel memory and 8 mb of user space (both measured with Task Manager). It's about 40 bytes/semaphore in kernel space and 80 bytes/semaphore in user space! (this in Win32... In 64 bits it'll probably double)

How can I find the exact amount of physical memory on Windows x86-32bit using Perl or any other language?

I need to know how much physical memory a windows machine has, using Perl.
I've tried using Win32::SystemInfo. However this module states the following caveat:
On Intel x86 computers with more than 2 GB and less than 4 GB of memory, the MemoryStatus function will always return 2 GB for TotalPhys. Similarly, if the total available memory is between 2 and 4 GB, AvailPhys will be rounded down to 2 GB.
So on a machine which has 2-4 GB of physical memory, I get a false answer.
Is there a way to get the correct amount of physical memory? Perhaps another module? Or directly using Win32::API?
Edit: From the comments people gave here, it looks like the limitation is in the Win32 API , and not specific to Win32::SystemInfo. However, the OS does know exactly how much physical ram is available, so there must be a way to extract that information. If not in Perl then maybe in another language?
As stated in the comments, this is an issue of GlobalMemoryStatus, as it can return answers up to 2GB. And GlobalMemoryStatusEX which solves this issue of the 2GB limit, but only works on 64 bit systems (as far as I can tell).
In the end I'm using the following Perl code, which uses Win32::OLE and WMI class Win32_PhysicalMemory, which returns the correct amount of physical memory even on 32bit systems:
use strict;
use warnings;
use English;
use Win32::OLE qw( EVENTS HRESULT in );
use Readonly;
sub get_physical_memory {
my $machine = shift || '.'; # Default to local machine
my Readonly $WMI_MEMORY_CLASS_NAME = 'Win32_PhysicalMemory';
my Readonly $MEGABYTE = 1024*1024;
my $WMI =
Win32::OLE->GetObject( "winmgmts:{impersonationLevel=impersonate,(security)}//$machine/" ) || die "Could not get Win32 object: $OS_ERROR";
my $total_capacity = 0;
foreach my $object ( in( $WMI->InstancesOf( $WMI_MEMORY_CLASS_NAME ) ) ) {
$total_capacity += $object->{Capacity};
}
my $total_capacity_in_mb = $total_capacity / $MEGABYTE;
print "Total Memory : $total_capacity_in_mb \n";
return $total_capacity_in_mb;
}
I can only assume that the caveats attending Win32::SystemInfo's results are also caveats attending the raw Win32 API calls, as Perl itself certainly has no problem handling such large numbers. In which case the possibility of extracting accurate information looks a bit bleak.
I've also heard in passing that current 32-bit versions of Windows can only use about 3.2Gb of RAM on a machine that has >= 4Gb installed, which may be hearsay, but which jibes with the limitation being in the API itself.
This information can be pulled from WMI, or using SNMP if you choose to enable SNMP on the box it will be running on. For WMI, I don't have a Perl example offhand but for a VBScript example see below.
Ref: http://www.microsoft.com/technet/scriptcenter/guide/sas_wmi_dieu.mspx
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer)
Set colSWbemObjectSet = _
objSWbemServices.InstancesOf("Win32_LogicalMemoryConfiguration")
For Each objSWbemObject In colSWbemObjectSet
Wscript.Echo "Total Physical Memory (kb): " & _
objSWbemObject.TotalPhysicalMemory
Next
Tested on my XP system and it retrieves the desired results (only 1.5GB RAM here, sorry). I'm quite sure there are WMI interfaces for Perl as well if you want to stick with Perl. If SNMP is an option, the total physical memory can be obtained from SNMP as well using one of the Perl SNMP libraries.
EDIT: Just noticed #Mr. Muskrat's comment regarding Microsoft KB http://support.microsoft.com/kb/274558 - evidently the behavior you're seeing with Perl is a limitation of the Win32 API call, so you might end up with the same results with WMI. Unfortunately I don't have a 2-4GB RAM machine to try this on to verify.

Resources